diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index 102c3793765..2407a2751c1 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -87,7 +87,8 @@ func newGatewayAPIController(mgr manager.Manager, cfg *config.Server, su status. if err := c.Watch( &source.Kind{Type: &gwapiv1b1.Gateway{}}, &handler.EnqueueRequestForObject{}, - predicate.NewPredicateFuncs(r.validateGatewayForReconcile)); err != nil { + predicate.NewPredicateFuncs(r.validateGatewayForReconcile), + ); err != nil { return err } if err := addGatewayIndexers(ctx, mgr); err != nil { @@ -124,7 +125,11 @@ func newGatewayAPIController(mgr manager.Manager, cfg *config.Server, su status. } // Watch Secret CRUDs and process affected Gateways. - if err := c.Watch(&source.Kind{Type: &corev1.Secret{}}, &handler.EnqueueRequestForObject{}); err != nil { + if err := c.Watch( + &source.Kind{Type: &corev1.Secret{}}, + &handler.EnqueueRequestForObject{}, + predicate.NewPredicateFuncs(r.validateSecretForReconcile), + ); err != nil { return err } diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index 37e2c5accfd..9629f9d7e9a 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -9,12 +9,17 @@ import ( "context" "github.com/envoyproxy/gateway/internal/gatewayapi" + "github.com/envoyproxy/gateway/internal/provider/utils" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) +// TODO: all predicate functions are unti test candidates. + // hasMatchingController returns true if the provided object is a GatewayClass // with a Spec.Controller string matching this Envoy Gateway's controller string, // or false otherwise. @@ -103,3 +108,27 @@ func (r *gatewayAPIReconciler) validateRouteParentReferences(refs []gwapiv1b1.Pa return true } + +func (r *gatewayAPIReconciler) validateSecretForReconcile(obj client.Object) bool { + secret, ok := obj.(*corev1.Secret) + if !ok { + r.log.Info("unexpected object type, bypassing reconciliation", "object", obj) + return false + } + + gwList := &gwapiv1b1.GatewayList{} + if err := r.client.List(context.Background(), gwList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(secretGatewayIndex, utils.NamespacedName(secret).String()), + }); err != nil { + r.log.Error(err, "unable to find associated HTTPRoutes") + return false + } + + for _, gw := range gwList.Items { + if !r.validateGatewayForReconcile(&gw) { + return false + } + } + + return true +}