Skip to content

Commit

Permalink
additions
Browse files Browse the repository at this point in the history
Signed-off-by: Shubham Chauhan <shubham@tetrate.io>
  • Loading branch information
chauhanshubham committed Dec 1, 2022
1 parent 3f725dd commit 57715a9
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 64 deletions.
2 changes: 2 additions & 0 deletions internal/message/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (

// ProviderResources message
type ProviderResources struct {
// GatewayAPIResources is a map from a GatewayClass name to
// a group of gateway API resources.
GatewayAPIResources watchable.Map[string, *gatewayapi.Resources]

GatewayStatuses watchable.Map[types.NamespacedName, *gwapiv1b1.Gateway]
Expand Down
78 changes: 14 additions & 64 deletions internal/provider/kubernetes/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ func newGatewayAPIController(mgr manager.Manager, cfg *config.Server, su status.
}

// Watch Service CRUDs and process affected *Route objects.
if err := c.Watch(&source.Kind{Type: &corev1.Service{}}, handler.EnqueueRequestsFromMapFunc(r.processServiceForOwningGateway)); err != nil {
if err := c.Watch(
&source.Kind{Type: &corev1.Service{}},
&handler.EnqueueRequestForObject{},
predicate.NewPredicateFuncs(r.validateServiceForReconcile)); err != nil {
return err
}

Expand All @@ -134,15 +137,22 @@ func newGatewayAPIController(mgr manager.Manager, cfg *config.Server, su status.
}

// Watch ReferenceGrant CRUDs and process affected Gateways.
if err := c.Watch(&source.Kind{Type: &gwapiv1a2.ReferenceGrant{}}, &handler.EnqueueRequestForObject{}); err != nil {
if err := c.Watch(
&source.Kind{Type: &gwapiv1a2.ReferenceGrant{}},
&handler.EnqueueRequestForObject{},
); err != nil {
return err
}
if err := addReferenceGrantIndexers(ctx, mgr); err != nil {
return err
}

// Watch Deployment CRUDs and process affected Gateways.
if err := c.Watch(&source.Kind{Type: &appsv1.Deployment{}}, handler.EnqueueRequestsFromMapFunc(r.processDeploymentForOwningGateway)); err != nil {
if err := c.Watch(
&source.Kind{Type: &appsv1.Deployment{}},
&handler.EnqueueRequestForObject{},
predicate.NewPredicateFuncs(r.validateDeploymentForReconcile),
); err != nil {
return err
}

Expand Down Expand Up @@ -368,7 +378,7 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, request reconcile.
to := ObjectKindNamespacedName{kind: gatewayapi.KindService, namespace: backendNamespace, name: string(backendRef.Name)}
refGrant, err := r.findReferenceGrant(ctx, from, to)
if err != nil {
r.log.Error(err, "unable to find ReferenceGrant that links the Service to TLSRoute")
r.log.Error(err, "unable to find ReferenceGrant that links the Service to HTTPRoute")
continue
}

Expand Down Expand Up @@ -461,66 +471,6 @@ func (r *gatewayAPIReconciler) getNamespace(ctx context.Context, name string) (*
return ns, nil
}

// processDeploymentForOwningGateway tries finding the owning Gateway of the Deployment
// if it exists, finds the Gateway's Service, and further updates the Gateway
// status Ready condition.
func (r *gatewayAPIReconciler) processDeploymentForOwningGateway(obj client.Object) (request []reconcile.Request) {
// Process Deployment Reconcile nothing.
ctx := context.Background()
deployment := obj.(*appsv1.Deployment)
if deployment == nil {
return
}

// Check if the deployment belongs to a Gateway, if so, find the Gateway.
gtw := r.findOwningGateway(ctx, deployment.GetLabels())
if gtw == nil {
return
}

// Check if the Service for the Gateway also exists, if it does, proceed with
// the Gateway status update.
svc, err := r.envoyServiceForGateway(ctx, gtw)
if err != nil {
r.log.Info("failed to get Service for gateway",
"namespace", gtw.Namespace, "name", gtw.Name)
return
}

r.statusUpdateForGateway(gtw, svc, deployment)
return
}

// processServiceForOwningGateway tries finding the owning Gateway of the Service
// if it exists, finds the Gateway's Deployment, and further updates the Gateway
// status Ready condition.
func (r *gatewayAPIReconciler) processServiceForOwningGateway(obj client.Object) (request []reconcile.Request) {
// Process Service Reconcile nothing.
ctx := context.Background()
svc := obj.(*corev1.Service)
if svc == nil {
return
}

// Check if the Service belongs to a Gateway, if so, find the Gateway.
gtw := r.findOwningGateway(ctx, svc.GetLabels())
if gtw == nil {
return
}

// Check if the Deployment for the Gateway also exists, if it does, proceed with
// the Gateway status update.
deployment, err := r.envoyDeploymentForGateway(ctx, gtw)
if err != nil {
r.log.Info("failed to get Deployment for gateway",
"namespace", gtw.Namespace, "name", gtw.Name)
return
}

r.statusUpdateForGateway(gtw, svc, deployment)
return
}

func (r gatewayAPIReconciler) findOwningGateway(ctx context.Context, labels map[string]string) *gwapiv1b1.Gateway {
gwName, ok := labels[gatewayapi.OwningGatewayNameLabel]
if !ok {
Expand Down
71 changes: 71 additions & 0 deletions internal/provider/kubernetes/predicates.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/envoyproxy/gateway/internal/gatewayapi"
"github.com/envoyproxy/gateway/internal/provider/utils"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -64,6 +65,7 @@ func (r *gatewayAPIReconciler) validateGatewayForReconcile(obj client.Object) bo
return true
}

// validateTLSRouteForReconcile checks whether the HTTPRoute refers any valid Gateway.
func (r *gatewayAPIReconciler) validateHTTPRouteForReconcile(obj client.Object) bool {
hr, ok := obj.(*gwapiv1b1.HTTPRoute)
if !ok {
Expand All @@ -75,6 +77,7 @@ func (r *gatewayAPIReconciler) validateHTTPRouteForReconcile(obj client.Object)
return r.validateRouteParentReferences(parentReferences, hr.Namespace)
}

// validateTLSRouteForReconcile checks whether the TLSRoute refers any valid Gateway.
func (r *gatewayAPIReconciler) validateTLSRouteForReconcile(obj client.Object) bool {
tr, ok := obj.(*gwapiv1a2.TLSRoute)
if !ok {
Expand All @@ -86,6 +89,8 @@ func (r *gatewayAPIReconciler) validateTLSRouteForReconcile(obj client.Object) b
return r.validateRouteParentReferences(parentReferences, tr.Namespace)
}

// validateRouteParentReferences checks whether the parent references of a given Route
// object, point to valid Gateways.
func (r *gatewayAPIReconciler) validateRouteParentReferences(refs []gwapiv1b1.ParentReference, defaultNamespace string) bool {
for _, ref := range refs {
if ref.Kind != nil && *ref.Kind == gatewayapi.KindGateway {
Expand All @@ -103,12 +108,17 @@ func (r *gatewayAPIReconciler) validateRouteParentReferences(refs []gwapiv1b1.Pa
if !r.validateGatewayForReconcile(gw) {
return false
}

// Even if one of the parent references points to a valid Gateway, we
// must reconcile the Route object.
return true
}
}

return true
}

// validateSecretForReconcile checks whether the Secret belongs to a valid Gateway.
func (r *gatewayAPIReconciler) validateSecretForReconcile(obj client.Object) bool {
secret, ok := obj.(*corev1.Secret)
if !ok {
Expand All @@ -133,3 +143,64 @@ func (r *gatewayAPIReconciler) validateSecretForReconcile(obj client.Object) boo

return true
}

// validateServiceForReconcile tries finding the owning Gateway of the Service
// if it exists, finds the Gateway's Deployment, and further updates the Gateway
// status Ready condition. All Services are pushed for reconciliation.
func (r *gatewayAPIReconciler) validateServiceForReconcile(obj client.Object) bool {
ctx := context.Background()
svc, ok := obj.(*corev1.Service)
if !ok {
r.log.Info("unexpected object type, bypassing reconciliation", "object", obj)
return false
}

// Check if the Service belongs to a Gateway, if so, find the Gateway. If
gtw := r.findOwningGateway(ctx, svc.GetLabels())
if gtw != nil {
// Check if the Deployment for the Gateway also exists, if it does, proceed with
// the Gateway status update.
deployment, err := r.envoyDeploymentForGateway(ctx, gtw)
if err != nil {
r.log.Info("failed to get Deployment for gateway",
"namespace", gtw.Namespace, "name", gtw.Name)
return false
}

r.statusUpdateForGateway(gtw, svc, deployment)
return true
}

// TODO: further filter only those services that are referred by HTTPRoutes
return true
}

// validateDeploymentForReconcile tries finding the owning Gateway of the Deployment
// if it exists, finds the Gateway's Service, and further updates the Gateway
// status Ready condition. No Deployments are pushed for reconciliation.
func (r *gatewayAPIReconciler) validateDeploymentForReconcile(obj client.Object) bool {
ctx := context.Background()
deployment, ok := obj.(*appsv1.Deployment)
if !ok {
r.log.Info("unexpected object type, bypassing reconciliation", "object", obj)
return false
}

// Check if the deployment belongs to a Gateway, if so, find the Gateway.
gtw := r.findOwningGateway(ctx, deployment.GetLabels())
if gtw != nil {
// Check if the Service for the Gateway also exists, if it does, proceed with
// the Gateway status update.
svc, err := r.envoyServiceForGateway(ctx, gtw)
if err != nil {
r.log.Info("failed to get Service for gateway",
"namespace", gtw.Namespace, "name", gtw.Name)
return false
}

r.statusUpdateForGateway(gtw, svc, deployment)
}

// There is no need to reconcile the Deployment any further.
return false
}

0 comments on commit 57715a9

Please sign in to comment.