Skip to content

Commit

Permalink
predicates pt1
Browse files Browse the repository at this point in the history
Signed-off-by: Shubham Chauhan <shubham@tetrate.io>
  • Loading branch information
chauhanshubham committed Nov 30, 2022
1 parent 9903b7f commit 9b1e601
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 22 deletions.
36 changes: 14 additions & 22 deletions internal/provider/kubernetes/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,23 +84,34 @@ func newGatewayAPIController(mgr manager.Manager, cfg *config.Server, su status.
}

// Watch Gateway CRUDs and reconcile affected GatewayClass.
if err := c.Watch(&source.Kind{Type: &gwapiv1b1.Gateway{}}, &handler.EnqueueRequestForObject{}); err != nil {
if err := c.Watch(
&source.Kind{Type: &gwapiv1b1.Gateway{}},
&handler.EnqueueRequestForObject{},
predicate.NewPredicateFuncs(r.validateGatewayForReconcile)); err != nil {
return err
}
if err := addGatewayIndexers(ctx, mgr); err != nil {
return err
}

// Watch HTTPRoute CRUDs and process affected Gateways.
if err := c.Watch(&source.Kind{Type: &gwapiv1b1.HTTPRoute{}}, &handler.EnqueueRequestForObject{}); err != nil {
if err := c.Watch(
&source.Kind{Type: &gwapiv1b1.HTTPRoute{}},
&handler.EnqueueRequestForObject{},
predicate.NewPredicateFuncs(r.validateHTTPRouteForReconcile),
); err != nil {
return err
}
if err := addHTTPRouteIndexers(ctx, mgr); err != nil {
return err
}

// Watch TLSRoute CRUDs and process affected Gateways.
if err := c.Watch(&source.Kind{Type: &gwapiv1a2.TLSRoute{}}, &handler.EnqueueRequestForObject{}); err != nil {
if err := c.Watch(
&source.Kind{Type: &gwapiv1a2.TLSRoute{}},
&handler.EnqueueRequestForObject{},
predicate.NewPredicateFuncs(r.validateTLSRouteForReconcile),
); err != nil {
return err
}
if err := addTLSRouteIndexers(ctx, mgr); err != nil {
Expand Down Expand Up @@ -633,25 +644,6 @@ func addTLSRouteIndexers(ctx context.Context, mgr manager.Manager) error {
return nil
}

// 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.
func (r *gatewayAPIReconciler) hasMatchingController(obj client.Object) bool {
gc, ok := obj.(*gwapiv1b1.GatewayClass)
if !ok {
r.log.Info("bypassing reconciliation due to unexpected object type", "type", obj)
return false
}

if gc.Spec.ControllerName == r.classController {
r.log.Info("gatewayclass has matching controller name, processing", "name", gc.Name)
return true
}

r.log.Info("bypassing reconciliation due to controller name", "controller", gc.Spec.ControllerName)
return false
}

// addGatewayIndexers adds indexing on Gateway, for Secret objects that are
// referenced in Gateway objects. This helps in querying for Gateways that are
// affected by a particular Secret CRUD.
Expand Down
105 changes: 105 additions & 0 deletions internal/provider/kubernetes/predicates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright Envoy Gateway Authors
// SPDX-License-Identifier: Apache-2.0
// The full text of the Apache license is available in the LICENSE file at
// the root of the repo.

package kubernetes

import (
"context"

"github.com/envoyproxy/gateway/internal/gatewayapi"
"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"
)

// 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.
func (r *gatewayAPIReconciler) hasMatchingController(obj client.Object) bool {
gc, ok := obj.(*gwapiv1b1.GatewayClass)
if !ok {
r.log.Info("bypassing reconciliation due to unexpected object type", "type", obj)
return false
}

if gc.Spec.ControllerName == r.classController {
r.log.Info("gatewayclass has matching controller name, processing", "name", gc.Name)
return true
}

r.log.Info("bypassing reconciliation due to controller name", "controller", gc.Spec.ControllerName)
return false
}

// validateGatewayForReconcile returns true if the provided object is a Gateway
// using a GatewayClass matching the configured gatewayclass controller name.
func (r *gatewayAPIReconciler) validateGatewayForReconcile(obj client.Object) bool {
gw, ok := obj.(*gwapiv1b1.Gateway)
if !ok {
r.log.Info("unexpected object type, bypassing reconciliation", "object", obj)
return false
}

gc := &gwapiv1b1.GatewayClass{}
key := types.NamespacedName{Name: string(gw.Spec.GatewayClassName)}
if err := r.client.Get(context.Background(), key, gc); err != nil {
r.log.Error(err, "failed to get gatewayclass", "name", gw.Spec.GatewayClassName)
return false
}

if gc.Spec.ControllerName != r.classController {
r.log.Info("gatewayclass name for gateway doesn't match configured name",
"namespace", gw.Namespace, "name", gw.Name)
return false
}

return true
}

func (r *gatewayAPIReconciler) validateHTTPRouteForReconcile(obj client.Object) bool {
hr, ok := obj.(*gwapiv1b1.HTTPRoute)
if !ok {
r.log.Info("unexpected object type, bypassing reconciliation", "object", obj)
return false
}

parentReferences := hr.Spec.ParentRefs
return r.validateRouteParentReferences(parentReferences, hr.Namespace)
}

func (r *gatewayAPIReconciler) validateTLSRouteForReconcile(obj client.Object) bool {
tr, ok := obj.(*gwapiv1a2.TLSRoute)
if !ok {
r.log.Info("unexpected object type, bypassing reconciliation", "object", obj)
return false
}

parentReferences := gatewayapi.UpgradeParentReferences(tr.Spec.ParentRefs)
return r.validateRouteParentReferences(parentReferences, tr.Namespace)
}

func (r *gatewayAPIReconciler) validateRouteParentReferences(refs []gwapiv1b1.ParentReference, defaultNamespace string) bool {
for _, ref := range refs {
if ref.Kind != nil && *ref.Kind == gatewayapi.KindGateway {
key := types.NamespacedName{
Namespace: gatewayapi.NamespaceDerefOr(ref.Namespace, defaultNamespace),
Name: string(ref.Name),
}

gw := &gwapiv1b1.Gateway{}
if err := r.client.Get(context.Background(), key, gw); err != nil {
r.log.Error(err, "failed to get gateway", "namespace", key.Namespace, "name", key.Name)
return false
}

if !r.validateGatewayForReconcile(gw) {
return false
}
}
}

return true
}

0 comments on commit 9b1e601

Please sign in to comment.