Skip to content

Commit

Permalink
feat: KongPluginBinding reconciler watchers (#571)
Browse files Browse the repository at this point in the history
* feat: targets watchers for KongPluginBinding

Signed-off-by: Mattia Lavacca <[email protected]>

* chore: CHANGELOG updated

Signed-off-by: Mattia Lavacca <[email protected]>

* add inNamespace list filter

Signed-off-by: Mattia Lavacca <[email protected]>

---------

Signed-off-by: Mattia Lavacca <[email protected]>
  • Loading branch information
mlavacca authored Sep 11, 2024
1 parent 89ca968 commit 4731ea6
Show file tree
Hide file tree
Showing 3 changed files with 255 additions and 6 deletions.
9 changes: 6 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,13 @@
- The `DataPlaneKonnectExtension` CRD has been introduced. Such a CRD can be attached
to a `DataPlane` via the extensions field to have a konnect-flavored `DataPlane`.
[#453](https://github.com/Kong/gateway-operator/pull/453)
- Entities created in Konnect are now labeled (or tagged for those that does not support labels)
with origin Kubernetes object's metadata: `k8s-name`, `k8s-namespace`, `k8s-uid`, `k8s-generation`,
`k8s-kind`, `k8s-group`, `k8s-version`.
- Entities created in Konnect are now labeled (or tagged for those that does not
support labels) with origin Kubernetes object's metadata: `k8s-name`, `k8s-namespace`,
`k8s-uid`, `k8s-generation`, `k8s-kind`, `k8s-group`, `k8s-version`.
[#565](https://github.com/Kong/gateway-operator/pull/565)
- Add `KongService`, `KongRoute`, `KongConsumer`, and `KongConsumerGroup` watchers
in the `KongPluginBinding` reconciler.
[#571](https://github.com/Kong/gateway-operator/pull/571)

### Fixed

Expand Down
80 changes: 80 additions & 0 deletions controller/konnect/index_kongpluginbinding.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ const (
IndexFieldKongPluginBindingKongPluginReference = "kongPluginRef"
// IndexFieldKongPluginBindingKongClusterPluginReference is the index field for KongClusterPlugin -> KongPluginBinding.
IndexFieldKongPluginBindingKongClusterPluginReference = "kongClusterPluginRef"
// IndexFieldKongPluginBindingKongServiceReference is the index field for KongService -> KongPluginBinding.
IndexFieldKongPluginBindingKongServiceReference = "kongServiceRef"
// IndexFieldKongPluginBindingKongServiceReference is the index field for KongRoute -> KongPluginBinding.
IndexFieldKongPluginBindingKongRouteReference = "kongRouteRef"
// IndexFieldKongPluginBindingKongServiceReference is the index field for KongConsumer -> KongPluginBinding.
IndexFieldKongPluginBindingKongConsumerReference = "kongConsumerRef"
// IndexFieldKongPluginBindingKongServiceReference is the index field for KongConsumerGroup -> KongPluginBinding.
IndexFieldKongPluginBindingKongConsumerGroupReference = "kongConsumerGroupRef"
)

// IndexOptionsForKongPluginBinding returns required Index options for KongPluginBinding reconclier.
Expand All @@ -26,6 +34,26 @@ func IndexOptionsForKongPluginBinding() []ReconciliationIndexOption {
IndexField: IndexFieldKongPluginBindingKongClusterPluginReference,
ExtractValue: kongClusterPluginReferencesFromKongPluginBinding,
},
{
IndexObject: &configurationv1alpha1.KongPluginBinding{},
IndexField: IndexFieldKongPluginBindingKongServiceReference,
ExtractValue: kongServiceReferencesFromKongPluginBinding,
},
{
IndexObject: &configurationv1alpha1.KongPluginBinding{},
IndexField: IndexFieldKongPluginBindingKongRouteReference,
ExtractValue: kongRouteReferencesFromKongPluginBinding,
},
{
IndexObject: &configurationv1alpha1.KongPluginBinding{},
IndexField: IndexFieldKongPluginBindingKongConsumerReference,
ExtractValue: kongConsumerReferencesFromKongPluginBinding,
},
{
IndexObject: &configurationv1alpha1.KongPluginBinding{},
IndexField: IndexFieldKongPluginBindingKongConsumerGroupReference,
ExtractValue: kongConsumerGroupReferencesFromKongPluginBinding,
},
}
}

Expand All @@ -52,3 +80,55 @@ func kongClusterPluginReferencesFromKongPluginBinding(obj client.Object) []strin
}
return []string{binding.Spec.PluginReference.Name}
}

// kongServiceReferencesFromKongPluginBinding returns name of referenced KongService in KongPluginBinding spec.
func kongServiceReferencesFromKongPluginBinding(obj client.Object) []string {
binding, ok := obj.(*configurationv1alpha1.KongPluginBinding)
if !ok {
return nil
}
if binding.Spec.Targets.ServiceReference == nil ||
binding.Spec.Targets.ServiceReference.Group != configurationv1alpha1.GroupVersion.Group ||
binding.Spec.Targets.ServiceReference.Kind != "KongService" {
return nil
}
return []string{binding.Spec.Targets.ServiceReference.Name}
}

// kongRouteReferencesFromKongPluginBinding returns name of referenced KongRoute in KongPluginBinding spec.
func kongRouteReferencesFromKongPluginBinding(obj client.Object) []string {
binding, ok := obj.(*configurationv1alpha1.KongPluginBinding)
if !ok {
return nil
}
if binding.Spec.Targets.RouteReference == nil ||
binding.Spec.Targets.RouteReference.Group != configurationv1alpha1.GroupVersion.Group ||
binding.Spec.Targets.RouteReference.Kind != "KongRoute" {
return nil
}
return []string{binding.Spec.Targets.RouteReference.Name}
}

// kongConsumerReferencesFromKongPluginBinding returns name of referenced KongConsumer in KongPluginBinding spec.
func kongConsumerReferencesFromKongPluginBinding(obj client.Object) []string {
binding, ok := obj.(*configurationv1alpha1.KongPluginBinding)
if !ok {
return nil
}
if binding.Spec.Targets.ConsumerReference == nil {
return nil
}
return []string{binding.Spec.Targets.ConsumerReference.Name}
}

// kongConsumerGroupReferencesFromKongPluginBinding returns name of referenced KongConsumerGroup in KongPluginBinding spec.
func kongConsumerGroupReferencesFromKongPluginBinding(obj client.Object) []string {
binding, ok := obj.(*configurationv1alpha1.KongPluginBinding)
if !ok {
return nil
}
if binding.Spec.Targets.ConsumerGroupReference == nil {
return nil
}
return []string{binding.Spec.Targets.ConsumerGroupReference.Name}
}
172 changes: 169 additions & 3 deletions controller/konnect/watch_kongpluginbinding.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

configurationv1 "github.com/kong/kubernetes-configuration/api/configuration/v1"
configurationv1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1"
configurationv1beta1 "github.com/kong/kubernetes-configuration/api/configuration/v1beta1"
konnectv1alpha1 "github.com/kong/kubernetes-configuration/api/konnect/v1alpha1"
)

Expand Down Expand Up @@ -80,9 +81,38 @@ func KongPluginBindingReconciliationWatchOptions(
),
)
},
// TODO(mlavacca): add KongService watch
// TODO(mlavacca): add KongConsumer watch
// TODO(mlavacca): add KongRoute watch
func(b *ctrl.Builder) *ctrl.Builder {
return b.Watches(
&configurationv1alpha1.KongService{},
handler.EnqueueRequestsFromMapFunc(
enqueueKongPluginBindingForKongService(cl),
),
)
},
func(b *ctrl.Builder) *ctrl.Builder {
return b.Watches(
&configurationv1alpha1.KongRoute{},
handler.EnqueueRequestsFromMapFunc(
enqueueKongPluginBindingForKongRoute(cl),
),
)
},
func(b *ctrl.Builder) *ctrl.Builder {
return b.Watches(
&configurationv1.KongConsumer{},
handler.EnqueueRequestsFromMapFunc(
enqueueKongPluginBindingForKongConsumer(cl),
),
)
},
func(b *ctrl.Builder) *ctrl.Builder {
return b.Watches(
&configurationv1beta1.KongConsumerGroup{},
handler.EnqueueRequestsFromMapFunc(
enqueueKongPluginBindingForKongConsumerGroup(cl),
),
)
},
}
}

Expand Down Expand Up @@ -306,3 +336,139 @@ func enqueueKongPluginBindingForKongClusterPlugin(cl client.Client) func(
})
}
}

func enqueueKongPluginBindingForKongService(cl client.Client) func(
ctx context.Context, obj client.Object) []reconcile.Request {
return func(ctx context.Context, obj client.Object) []reconcile.Request {
kongService, ok := obj.(*configurationv1alpha1.KongService)
if !ok {
return nil
}

pluginBindingList := configurationv1alpha1.KongPluginBindingList{}
err := cl.List(ctx, &pluginBindingList,
client.InNamespace(kongService.Namespace),
client.MatchingFields{
IndexFieldKongPluginBindingKongServiceReference: kongService.Name,
},
)
if err != nil {
ctrllog.FromContext(ctx).Error(err, "failed to list KongPluginBindings referencing KongServices")
}

return lo.FilterMap(pluginBindingList.Items, func(pb configurationv1alpha1.KongPluginBinding, _ int) (reconcile.Request, bool) {
// Only put KongPluginBindings referencing to a Konnect control plane,
if pb.Spec.ControlPlaneRef == nil || pb.Spec.ControlPlaneRef.Type != configurationv1alpha1.ControlPlaneRefKonnectNamespacedRef {
return reconcile.Request{}, false
}
return reconcile.Request{
NamespacedName: types.NamespacedName{
Namespace: pb.Namespace,
Name: pb.Name,
},
}, true
})
}
}

func enqueueKongPluginBindingForKongRoute(cl client.Client) func(
ctx context.Context, obj client.Object) []reconcile.Request {
return func(ctx context.Context, obj client.Object) []reconcile.Request {
kongRoute, ok := obj.(*configurationv1alpha1.KongRoute)
if !ok {
return nil
}

pluginBindingList := configurationv1alpha1.KongPluginBindingList{}
err := cl.List(ctx, &pluginBindingList,
client.InNamespace(kongRoute.Namespace),
client.MatchingFields{
IndexFieldKongPluginBindingKongRouteReference: kongRoute.Name,
},
)
if err != nil {
ctrllog.FromContext(ctx).Error(err, "failed to list KongPluginBindings referencing KongRoutes")
}

return lo.FilterMap(pluginBindingList.Items, func(pb configurationv1alpha1.KongPluginBinding, _ int) (reconcile.Request, bool) {
// Only put KongPluginBindings referencing to a Konnect control plane,
if pb.Spec.ControlPlaneRef == nil || pb.Spec.ControlPlaneRef.Type != configurationv1alpha1.ControlPlaneRefKonnectNamespacedRef {
return reconcile.Request{}, false
}
return reconcile.Request{
NamespacedName: types.NamespacedName{
Namespace: pb.Namespace,
Name: pb.Name,
},
}, true
})
}
}

func enqueueKongPluginBindingForKongConsumer(cl client.Client) func(
ctx context.Context, obj client.Object) []reconcile.Request {
return func(ctx context.Context, obj client.Object) []reconcile.Request {
kongConsumer, ok := obj.(*configurationv1.KongConsumer)
if !ok {
return nil
}

pluginBindingList := configurationv1alpha1.KongPluginBindingList{}
err := cl.List(ctx, &pluginBindingList,
client.InNamespace(kongConsumer.Namespace),
client.MatchingFields{
IndexFieldKongPluginBindingKongConsumerReference: kongConsumer.Name,
},
)
if err != nil {
ctrllog.FromContext(ctx).Error(err, "failed to list KongPluginBindings referencing KongConsumers")
}

return lo.FilterMap(pluginBindingList.Items, func(pb configurationv1alpha1.KongPluginBinding, _ int) (reconcile.Request, bool) {
// Only put KongPluginBindings referencing to a Konnect control plane,
if pb.Spec.ControlPlaneRef == nil || pb.Spec.ControlPlaneRef.Type != configurationv1alpha1.ControlPlaneRefKonnectNamespacedRef {
return reconcile.Request{}, false
}
return reconcile.Request{
NamespacedName: types.NamespacedName{
Namespace: pb.Namespace,
Name: pb.Name,
},
}, true
})
}
}

func enqueueKongPluginBindingForKongConsumerGroup(cl client.Client) func(
ctx context.Context, obj client.Object) []reconcile.Request {
return func(ctx context.Context, obj client.Object) []reconcile.Request {
kongConsumerGroup, ok := obj.(*configurationv1beta1.KongConsumerGroup)
if !ok {
return nil
}

pluginBindingList := configurationv1alpha1.KongPluginBindingList{}
err := cl.List(ctx, &pluginBindingList,
client.InNamespace(kongConsumerGroup.Namespace),
client.MatchingFields{
IndexFieldKongPluginBindingKongConsumerGroupReference: kongConsumerGroup.Name,
},
)
if err != nil {
ctrllog.FromContext(ctx).Error(err, "failed to list KongPluginBindings referencing KongConsumerGroups")
}

return lo.FilterMap(pluginBindingList.Items, func(pb configurationv1alpha1.KongPluginBinding, _ int) (reconcile.Request, bool) {
// Only put KongPluginBindings referencing to a Konnect control plane,
if pb.Spec.ControlPlaneRef == nil || pb.Spec.ControlPlaneRef.Type != configurationv1alpha1.ControlPlaneRefKonnectNamespacedRef {
return reconcile.Request{}, false
}
return reconcile.Request{
NamespacedName: types.NamespacedName{
Namespace: pb.Namespace,
Name: pb.Name,
},
}, true
})
}
}

0 comments on commit 4731ea6

Please sign in to comment.