Skip to content

feat: Add ReferenceGrant support for HTTPRoute #149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
May 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/v1alpha1/backendtrafficpolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ type BackendTrafficPolicy struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// BackendTrafficPolicySpec defines traffic handling policies applied to backend services,
// such as load balancing strategy, connection settings, and failover behavior.
// BackendTrafficPolicySpec defines traffic handling policies applied to backend services,
// such as load balancing strategy, connection settings, and failover behavior.
Spec BackendTrafficPolicySpec `json:"spec,omitempty"`
Status PolicyStatus `json:"status,omitempty"`
}
Expand Down
18 changes: 9 additions & 9 deletions api/v1alpha1/consumer_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ type Consumer struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// ConsumerSpec defines the configuration for a consumer, including consumer name,
// ConsumerSpec defines the configuration for a consumer, including consumer name,
// authentication credentials, and plugin settings.
Spec ConsumerSpec `json:"spec,omitempty"`
Status Status `json:"status,omitempty"`
}

type ConsumerSpec struct {
// GatewayRef specifies the gateway details.
GatewayRef GatewayRef `json:"gatewayRef,omitempty"`
GatewayRef GatewayRef `json:"gatewayRef,omitempty"`
// Credentials specifies the credential details of a consumer.
Credentials []Credential `json:"credentials,omitempty"`
// Plugins define the plugins associated with a consumer.
Plugins []Plugin `json:"plugins,omitempty"`
Plugins []Plugin `json:"plugins,omitempty"`
}

type GatewayRef struct {
Expand All @@ -48,7 +48,7 @@ type GatewayRef struct {
Kind *string `json:"kind,omitempty"`
// Group is the API group the resource belongs to. Default is `gateway.networking.k8s.io`.
// +kubebuilder:default=gateway.networking.k8s.io
Group *string `json:"group,omitempty"`
Group *string `json:"group,omitempty"`
// Namespace is namespace of the resource.
Namespace *string `json:"namespace,omitempty"`
}
Expand All @@ -58,18 +58,18 @@ type Credential struct {
// +kubebuilder:validation:Enum=jwt-auth;basic-auth;key-auth;hmac-auth;
// Type specifies the type of authentication to configure credentials for.
// Can be one of `jwt-auth`, `basic-auth`, `key-auth`, or `hmac-auth`.
Type string `json:"type"`
Type string `json:"type"`
// Config specifies the credential details for authentication.
Config apiextensionsv1.JSON `json:"config,omitempty"`
Config apiextensionsv1.JSON `json:"config,omitempty"`
// SecretRef references to the Secret that contains the credentials.
SecretRef *SecretReference `json:"secretRef,omitempty"`
SecretRef *SecretReference `json:"secretRef,omitempty"`
// Name is the name of the credential.
Name string `json:"name,omitempty"`
Name string `json:"name,omitempty"`
}

type SecretReference struct {
// Name is the name of the secret.
Name string `json:"name"`
Name string `json:"name"`
// Namespace is the namespace of the secret.
Namespace *string `json:"namespace,omitempty"`
}
Expand Down
20 changes: 10 additions & 10 deletions api/v1alpha1/gatewayproxy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ type GatewayProxySpec struct {

// PublishService specifies the LoadBalancer-type Service whose external address the controller uses to
// update the status of Ingress resources.
PublishService string `json:"publishService,omitempty"`
PublishService string `json:"publishService,omitempty"`
// StatusAddress specifies the external IP addresses that the controller uses to populate the status field
// of GatewayProxy or Ingress resources for developers to access.
StatusAddress []string `json:"statusAddress,omitempty"`
StatusAddress []string `json:"statusAddress,omitempty"`
// Provider configures the provider details.
Provider *GatewayProxyProvider `json:"provider,omitempty"`
Provider *GatewayProxyProvider `json:"provider,omitempty"`
// Plugins configure global plugins.
Plugins []GatewayProxyPlugin `json:"plugins,omitempty"`
Plugins []GatewayProxyPlugin `json:"plugins,omitempty"`
// PluginMetadata configures common configurations shared by all plugin instances of the same name.
PluginMetadata map[string]apiextensionsv1.JSON `json:"pluginMetadata,omitempty"`
}
Expand Down Expand Up @@ -132,8 +132,8 @@ type GatewayProxy struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// GatewayProxySpec defines the desired state and configuration of a GatewayProxy,
// including networking settings, global plugins, and plugin metadata.
// GatewayProxySpec defines the desired state and configuration of a GatewayProxy,
// including networking settings, global plugins, and plugin metadata.
Spec GatewayProxySpec `json:"spec,omitempty"`
}

Expand All @@ -148,11 +148,11 @@ type GatewayProxyList struct {
// GatewayProxyPlugin contains plugin configurations.
type GatewayProxyPlugin struct {
// Name is the name of the plugin.
Name string `json:"name,omitempty"`
// Enabled defines whether the plugin is enabled.
Enabled bool `json:"enabled,omitempty"`
Name string `json:"name,omitempty"`
// Enabled defines whether the plugin is enabled.
Enabled bool `json:"enabled,omitempty"`
// Config defines the plugin's configuration details.
Config apiextensionsv1.JSON `json:"config,omitempty"`
Config apiextensionsv1.JSON `json:"config,omitempty"`
}

func init() {
Expand Down
4 changes: 2 additions & 2 deletions api/v1alpha1/httproutepolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ type HTTPRoutePolicySpec struct {
// +kubebuilder:validation:MaxItems=16
TargetRefs []gatewayv1alpha2.LocalPolicyTargetReferenceWithSectionName `json:"targetRefs"`
// Priority sets the priority for route. A higher value sets a higher priority in route matching.
Priority *int64 `json:"priority,omitempty" yaml:"priority,omitempty"`
Priority *int64 `json:"priority,omitempty" yaml:"priority,omitempty"`
// Vars sets the request matching conditions.
Vars []apiextensionsv1.JSON `json:"vars,omitempty" yaml:"vars,omitempty"`
Vars []apiextensionsv1.JSON `json:"vars,omitempty" yaml:"vars,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
65 changes: 18 additions & 47 deletions internal/controller/gateway_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"
"reflect"

"github.com/api7/gopkg/pkg/log"
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -26,15 +27,12 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
"sigs.k8s.io/gateway-api/apis/v1beta1"

"github.com/api7/gopkg/pkg/log"

"github.com/apache/apisix-ingress-controller/api/v1alpha1"
"github.com/apache/apisix-ingress-controller/internal/controller/indexer"
"github.com/apache/apisix-ingress-controller/internal/provider"
Expand All @@ -51,7 +49,7 @@ type GatewayReconciler struct { //nolint:revive

// SetupWithManager sets up the controller with the Manager.
func (r *GatewayReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
bdr := ctrl.NewControllerManagedBy(mgr).
For(
&gatewayv1.Gateway{},
builder.WithPredicates(
Expand Down Expand Up @@ -85,25 +83,16 @@ func (r *GatewayReconciler) SetupWithManager(mgr ctrl.Manager) error {
Watches(
&corev1.Secret{},
handler.EnqueueRequestsFromMapFunc(r.listGatewaysForSecret),
).
Watches(&v1beta1.ReferenceGrant{},
)

if GetEnableReferenceGrant() {
bdr.Watches(&v1beta1.ReferenceGrant{},
handler.EnqueueRequestsFromMapFunc(r.listReferenceGrantsForGateway),
builder.WithPredicates(predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
return referenceGrantHasGatewayFrom(e.Object)
},
UpdateFunc: func(e event.UpdateEvent) bool {
return referenceGrantHasGatewayFrom(e.ObjectOld) || referenceGrantHasGatewayFrom(e.ObjectNew)
},
DeleteFunc: func(e event.DeleteEvent) bool {
return referenceGrantHasGatewayFrom(e.Object)
},
GenericFunc: func(e event.GenericEvent) bool {
return referenceGrantHasGatewayFrom(e.Object)
},
}),
).
Complete(r)
builder.WithPredicates(referenceGrantPredicates(KindGateway)),
)
}

return bdr.Complete(r)
}

func (r *GatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
Expand Down Expand Up @@ -184,14 +173,9 @@ func (r *GatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
}
}

var referenceGrantList v1beta1.ReferenceGrantList
if err := r.List(ctx, &referenceGrantList); err != nil {
r.Log.Error(err, "failed to list reference grants")
return ctrl.Result{}, err
}
listenerStatuses, err := getListenerStatus(ctx, r.Client, gateway, referenceGrantList.Items)
listenerStatuses, err := getListenerStatus(ctx, r.Client, gateway)
if err != nil {
r.Log.Error(err, "failed to get listener status", "gateway", types.NamespacedName{Namespace: gateway.GetNamespace(), Name: gateway.GetName()})
r.Log.Error(err, "failed to get listener status", "gateway", req.NamespacedName)
return ctrl.Result{}, err
}

Expand Down Expand Up @@ -391,12 +375,12 @@ func (r *GatewayReconciler) listReferenceGrantsForGateway(ctx context.Context, o
}

for _, gateway := range gatewayList.Items {
gw := v1beta1.ReferenceGrantFrom{
Group: gatewayv1.GroupName,
Kind: KindGateway,
Namespace: v1beta1.Namespace(gateway.GetNamespace()),
}
for _, from := range grant.Spec.From {
gw := v1beta1.ReferenceGrantFrom{
Group: gatewayv1.GroupName,
Kind: KindGateway,
Namespace: v1beta1.Namespace(gateway.GetNamespace()),
}
if from == gw {
requests = append(requests, reconcile.Request{
NamespacedName: types.NamespacedName{
Expand All @@ -410,19 +394,6 @@ func (r *GatewayReconciler) listReferenceGrantsForGateway(ctx context.Context, o
return requests
}

func referenceGrantHasGatewayFrom(obj client.Object) bool {
grant, ok := obj.(*v1beta1.ReferenceGrant)
if !ok {
return false
}
for _, from := range grant.Spec.From {
if from.Kind == KindGateway && string(from.Group) == gatewayv1.GroupName {
return true
}
}
return false
}

func (r *GatewayReconciler) processInfrastructure(tctx *provider.TranslateContext, gateway *gatewayv1.Gateway) error {
rk := provider.ResourceKind{
Kind: gateway.Kind,
Expand Down
Loading
Loading