From 3645df34acebbba11fe8cb4f721aa7ac560242a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Ma=C5=82ek?= Date: Wed, 2 Oct 2024 18:00:51 +0200 Subject: [PATCH 1/2] feat(konnect): add indices for KongPluginBinding -> KonnectGatewayControlPlane and KongRoute -> KongService --- controller/konnect/index_kongpluginbinding.go | 51 +++++++++++++++---- controller/konnect/index_kongroute.go | 27 ++++++++++ controller/konnect/watch_kongpluginbinding.go | 46 +++-------------- controller/konnect/watch_kongroute.go | 48 +++-------------- 4 files changed, 83 insertions(+), 89 deletions(-) diff --git a/controller/konnect/index_kongpluginbinding.go b/controller/konnect/index_kongpluginbinding.go index 99146a404..df054e866 100644 --- a/controller/konnect/index_kongpluginbinding.go +++ b/controller/konnect/index_kongpluginbinding.go @@ -7,16 +7,18 @@ import ( ) const ( - // IndexFieldKongPluginBindingKongPluginReference is the index field for KongPlugin -> KongPluginBinding. - IndexFieldKongPluginBindingKongPluginReference = "kongPluginRef" - // IndexFieldKongPluginBindingKongServiceReference is the index field for KongService -> KongPluginBinding. - IndexFieldKongPluginBindingKongServiceReference = "kongServiceRef" - // IndexFieldKongPluginBindingKongRouteReference is the index field for KongRoute -> KongPluginBinding. - IndexFieldKongPluginBindingKongRouteReference = "kongRouteRef" - // IndexFieldKongPluginBindingKongConsumerReference is the index field for KongConsumer -> KongPluginBinding. - IndexFieldKongPluginBindingKongConsumerReference = "kongConsumerRef" - // IndexFieldKongPluginBindingKongConsumerGroupReference is the index field for KongConsumerGroup -> KongPluginBinding. - IndexFieldKongPluginBindingKongConsumerGroupReference = "kongConsumerGroupRef" + // IndexFieldKongPluginBindingKongPluginReference is the index field for KongPluginBinding -> KongPlugin. + IndexFieldKongPluginBindingKongPluginReference = "kongPluginBindingPluginRef" + // IndexFieldKongPluginBindingKongServiceReference is the index field for KongPluginBinding -> KongService. + IndexFieldKongPluginBindingKongServiceReference = "kongPluginBindingServiceRef" + // IndexFieldKongPluginBindingKongRouteReference is the index field for KongPluginBinding -> KongRoute. + IndexFieldKongPluginBindingKongRouteReference = "kongPluginBindingRouteRef" + // IndexFieldKongPluginBindingKongConsumerReference is the index field for KongPluginBinding -> KongConsumer. + IndexFieldKongPluginBindingKongConsumerReference = "kongPluginBindingConsumerRef" + // IndexFieldKongPluginBindingKongConsumerGroupReference is the index field for KongPluginBinding -> KongConsumerGroup. + IndexFieldKongPluginBindingKongConsumerGroupReference = "kongPluginBindingConsumerGroupRef" + // IndexFieldKongPluginBindingKonnectGatewayControlPlane is the index field for KongPluginBinding -> KonnectGatewayControlPlane. + IndexFieldKongPluginBindingKonnectGatewayControlPlane = "kongPluginBindingKonnectGatewayControlPlaneRef" ) // IndexOptionsForKongPluginBinding returns required Index options for KongPluginBinding reconclier. @@ -47,6 +49,11 @@ func IndexOptionsForKongPluginBinding() []ReconciliationIndexOption { IndexField: IndexFieldKongPluginBindingKongConsumerGroupReference, ExtractValue: kongConsumerGroupReferencesFromKongPluginBinding, }, + { + IndexObject: &configurationv1alpha1.KongPluginBinding{}, + IndexField: IndexFieldKongPluginBindingKonnectGatewayControlPlane, + ExtractValue: kongPluginBindingReferencesKonnectGatewayControlPlane, + }, } } @@ -113,3 +120,27 @@ func kongConsumerGroupReferencesFromKongPluginBinding(obj client.Object) []strin } return []string{binding.Spec.Targets.ConsumerGroupReference.Name} } + +// kongPluginBindingReferencesKonnectGatewayControlPlane returns name of referenced KonnectGatewayControlPlane in KongPluginBinding spec. +func kongPluginBindingReferencesKonnectGatewayControlPlane(obj client.Object) []string { + binding, ok := obj.(*configurationv1alpha1.KongPluginBinding) + if !ok { + return nil + } + cpRef := binding.Spec.ControlPlaneRef + if cpRef == nil || + cpRef.Type != configurationv1alpha1.ControlPlaneRefKonnectNamespacedRef || + cpRef.KonnectNamespacedRef == nil { + return nil + } + + // NOTE: This provides support for setting the namespace of the KonnectGatewayControlPlane ref + // but CRDs have validation rules in place which will disallow this until + // cross namespace refs are allowed. + namespace := binding.Namespace + if cpRef.KonnectNamespacedRef.Namespace != "" { + namespace = cpRef.KonnectNamespacedRef.Namespace + } + + return []string{namespace + "/" + cpRef.KonnectNamespacedRef.Name} +} diff --git a/controller/konnect/index_kongroute.go b/controller/konnect/index_kongroute.go index 31289d01e..3179dea65 100644 --- a/controller/konnect/index_kongroute.go +++ b/controller/konnect/index_kongroute.go @@ -11,6 +11,8 @@ import ( const ( // IndexFieldKongRouteOnReferencedPluginNames is the index field for KongRoute -> KongPlugin. IndexFieldKongRouteOnReferencedPluginNames = "kongRouteKongPluginRef" + // IndexFieldKongRouteOnReferencedKongService is the index field for KongRoute -> KongService. + IndexFieldKongRouteOnReferencedKongService = "kongRouteKongServiceRef" ) // IndexOptionsForKongRoute returns required Index options for KongRoute reconciler. @@ -21,6 +23,11 @@ func IndexOptionsForKongRoute() []ReconciliationIndexOption { IndexField: IndexFieldKongRouteOnReferencedPluginNames, ExtractValue: kongRouteUsesPlugins, }, + { + IndexObject: &configurationv1alpha1.KongRoute{}, + IndexField: IndexFieldKongRouteOnReferencedKongService, + ExtractValue: kongRouteRefersToKongService, + }, } } @@ -31,3 +38,23 @@ func kongRouteUsesPlugins(object client.Object) []string { } return annotations.ExtractPluginsWithNamespaces(route) } + +func kongRouteRefersToKongService(object client.Object) []string { + route, ok := object.(*configurationv1alpha1.KongRoute) + if !ok { + return nil + } + svcRef := route.Spec.ServiceRef + if svcRef == nil || + svcRef.Type != configurationv1alpha1.ServiceRefNamespacedRef || + svcRef.NamespacedRef == nil { + return nil + } + + namespace := route.Namespace + if svcRef.NamespacedRef.Namespace != "" { + namespace = svcRef.NamespacedRef.Namespace + } + + return []string{namespace + "/" + svcRef.NamespacedRef.Name} +} diff --git a/controller/konnect/watch_kongpluginbinding.go b/controller/konnect/watch_kongpluginbinding.go index 7b0369f3b..5dcaeab05 100644 --- a/controller/konnect/watch_kongpluginbinding.go +++ b/controller/konnect/watch_kongpluginbinding.go @@ -194,49 +194,17 @@ func enqueueKongPluginBindingForKonnectGatewayControlPlane( return nil } var l configurationv1alpha1.KongPluginBindingList - if err := cl.List(ctx, &l, &client.ListOptions{ + if err := cl.List(ctx, &l, // TODO: change this when cross namespace refs are allowed. - Namespace: cp.GetNamespace(), - }); err != nil { + client.InNamespace(cp.GetNamespace()), + client.MatchingFields{ + IndexFieldKongPluginBindingKonnectGatewayControlPlane: cp.Namespace + "/" + cp.Name, + }, + ); err != nil { return nil } - var ret []reconcile.Request - for _, pb := range l.Items { - if pb.Spec.ControlPlaneRef == nil { - continue - } - switch pb.Spec.ControlPlaneRef.Type { - case configurationv1alpha1.ControlPlaneRefKonnectNamespacedRef: - // TODO: change this when cross namespace refs are allowed. - if pb.Spec.ControlPlaneRef.KonnectNamespacedRef.Name != cp.Name { - continue - } - - ret = append(ret, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Namespace: pb.Namespace, - Name: pb.Name, - }, - }) - - case configurationv1alpha1.ControlPlaneRefKonnectID: - ctrllog.FromContext(ctx).Error( - fmt.Errorf("unimplemented ControlPlaneRef type %q", pb.Spec.ControlPlaneRef.Type), - "unimplemented ControlPlaneRef for KongPluginBinding", - "KongPluginBinding", pb, "refType", pb.Spec.ControlPlaneRef.Type, - ) - continue - - default: - ctrllog.FromContext(ctx).V(logging.DebugLevel.Value()).Info( - "unsupported ControlPlaneRef for KongPluginBinding", - "KongPluginBinding", pb, "refType", pb.Spec.ControlPlaneRef.Type, - ) - continue - } - } - return ret + return objectListToReconcileRequests(l.Items) } } diff --git a/controller/konnect/watch_kongroute.go b/controller/konnect/watch_kongroute.go index 7c16a6264..09c404271 100644 --- a/controller/konnect/watch_kongroute.go +++ b/controller/konnect/watch_kongroute.go @@ -14,7 +14,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" operatorerrors "github.com/kong/gateway-operator/internal/errors" - "github.com/kong/gateway-operator/modules/manager/logging" configurationv1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1" ) @@ -98,52 +97,21 @@ func enqueueKongRouteForKongService( // If the KongService does not refer to a KonnectGatewayControlPlane, // we do not need to enqueue any KongRoutes bound to this KongService. - cpRef := kongSvc.Spec.ControlPlaneRef - if cpRef == nil || cpRef.Type != configurationv1alpha1.ControlPlaneRefKonnectNamespacedRef { + if !objHasControlPlaneRefKonnectNamespacedRef(kongSvc) { return nil } var l configurationv1alpha1.KongRouteList - if err := cl.List(ctx, &l, &client.ListOptions{ + if err := cl.List(ctx, &l, // TODO: change this when cross namespace refs are allowed. - Namespace: kongSvc.GetNamespace(), - }); err != nil { + client.InNamespace(kongSvc.GetNamespace()), + client.MatchingFields{ + IndexFieldKongRouteOnReferencedKongService: kongSvc.Namespace + "/" + kongSvc.Name, + }, + ); err != nil { return nil } - var ret []reconcile.Request - for _, route := range l.Items { - svcRef, ok := getServiceRef(&route).Get() - if !ok { - continue - } - - switch svcRef.Type { - case configurationv1alpha1.ServiceRefNamespacedRef: - if svcRef.NamespacedRef == nil { - continue - } - - // TODO: change this when cross namespace refs are allowed. - if svcRef.NamespacedRef.Name != kongSvc.GetName() { - continue - } - - ret = append(ret, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Namespace: route.Namespace, - Name: route.Name, - }, - }) - - default: - ctrllog.FromContext(ctx).V(logging.DebugLevel.Value()).Info( - "unsupported ServiceRef for KongRoute", - "KongRoute", route, "refType", svcRef.Type, - ) - continue - } - } - return ret + return objectListToReconcileRequests(l.Items) } } From 0dd95837a5efd9de2818717f6bd752d8fb3ea514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Ma=C5=82ek?= Date: Thu, 3 Oct 2024 09:16:10 +0200 Subject: [PATCH 2/2] chore: add comment about not supporting cross namespace references between KongRoute and KongService --- controller/konnect/index_kongroute.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/controller/konnect/index_kongroute.go b/controller/konnect/index_kongroute.go index 3179dea65..15758ecc6 100644 --- a/controller/konnect/index_kongroute.go +++ b/controller/konnect/index_kongroute.go @@ -51,10 +51,8 @@ func kongRouteRefersToKongService(object client.Object) []string { return nil } - namespace := route.Namespace - if svcRef.NamespacedRef.Namespace != "" { - namespace = svcRef.NamespacedRef.Namespace - } + // NOTE: We currently do not allow cross namespace references between KongRoute and KongService. + // https://github.com/Kong/kubernetes-configuration/issues/106 tracks the implementation. - return []string{namespace + "/" + svcRef.NamespacedRef.Name} + return []string{route.Namespace + "/" + svcRef.NamespacedRef.Name} }