From 8aa432c1572df3a2e195724f55f1efc7cb37a007 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Sat, 27 Jan 2024 07:47:33 +0800 Subject: [PATCH 1/3] =?UTF-8?q?Trigger=20a=20reconcile=20of=20SecurityPoli?= =?UTF-8?q?cy=20when=20OIDC=20or=20Basic=20Auth=20secrets=E2=80=A6=20(#250?= =?UTF-8?q?5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * trigger a reconcile of SecurityPolicy when OIDC or Basic Auth secrets change Signed-off-by: huabing zhao * add tests Signed-off-by: huabing zhao * move status updating to a separate file Signed-off-by: huabing zhao --------- Signed-off-by: huabing zhao --- internal/provider/kubernetes/controller.go | 445 +++--------------- internal/provider/kubernetes/predicates.go | 36 +- .../provider/kubernetes/predicates_test.go | 65 ++- internal/provider/kubernetes/status.go | 411 ++++++++++++++++ 4 files changed, 564 insertions(+), 393 deletions(-) create mode 100644 internal/provider/kubernetes/status.go diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index cb6903b45e0..0e1ae250039 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -43,19 +43,20 @@ import ( ) const ( - classGatewayIndex = "classGatewayIndex" - gatewayTLSRouteIndex = "gatewayTLSRouteIndex" - gatewayHTTPRouteIndex = "gatewayHTTPRouteIndex" - gatewayGRPCRouteIndex = "gatewayGRPCRouteIndex" - gatewayTCPRouteIndex = "gatewayTCPRouteIndex" - gatewayUDPRouteIndex = "gatewayUDPRouteIndex" - secretGatewayIndex = "secretGatewayIndex" - targetRefGrantRouteIndex = "targetRefGrantRouteIndex" - backendHTTPRouteIndex = "backendHTTPRouteIndex" - backendGRPCRouteIndex = "backendGRPCRouteIndex" - backendTLSRouteIndex = "backendTLSRouteIndex" - backendTCPRouteIndex = "backendTCPRouteIndex" - backendUDPRouteIndex = "backendUDPRouteIndex" + classGatewayIndex = "classGatewayIndex" + gatewayTLSRouteIndex = "gatewayTLSRouteIndex" + gatewayHTTPRouteIndex = "gatewayHTTPRouteIndex" + gatewayGRPCRouteIndex = "gatewayGRPCRouteIndex" + gatewayTCPRouteIndex = "gatewayTCPRouteIndex" + gatewayUDPRouteIndex = "gatewayUDPRouteIndex" + secretGatewayIndex = "secretGatewayIndex" + targetRefGrantRouteIndex = "targetRefGrantRouteIndex" + backendHTTPRouteIndex = "backendHTTPRouteIndex" + backendGRPCRouteIndex = "backendGRPCRouteIndex" + backendTLSRouteIndex = "backendTLSRouteIndex" + backendTCPRouteIndex = "backendTCPRouteIndex" + backendUDPRouteIndex = "backendUDPRouteIndex" + secretSecurityPolicyIndex = "secretSecurityPolicyIndex" ) type gatewayAPIReconciler struct { @@ -189,7 +190,7 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques // Update status for all gateway classes for _, gc := range cc.notAcceptedClasses() { - if err := r.gatewayClassUpdater(ctx, gc, false, string(status.ReasonOlderGatewayClassExists), + if err := r.updateStatusForGatewayClass(ctx, gc, false, string(status.ReasonOlderGatewayClassExists), status.MsgOlderGatewayClassExists); err != nil { r.resources.GatewayAPIResources.Delete(acceptedGC.Name) return reconcile.Result{}, err @@ -347,7 +348,7 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques if acceptedGC.Spec.ParametersRef != nil && acceptedGC.DeletionTimestamp == nil { if err := r.processParamsRef(ctx, acceptedGC, resourceTree); err != nil { msg := fmt.Sprintf("%s: %v", status.MsgGatewayClassInvalidParams, err) - if err := r.gatewayClassUpdater(ctx, acceptedGC, false, string(gwapiv1.GatewayClassReasonInvalidParameters), msg); err != nil { + if err := r.updateStatusForGatewayClass(ctx, acceptedGC, false, string(gwapiv1.GatewayClassReasonInvalidParameters), msg); err != nil { r.log.Error(err, "unable to update GatewayClass status") } r.log.Error(err, "failed to process parametersRef for gatewayclass", "name", acceptedGC.Name) @@ -359,7 +360,7 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques r.mergeGateways = *resourceTree.EnvoyProxy.Spec.MergeGateways } - if err := r.gatewayClassUpdater(ctx, acceptedGC, true, string(gwapiv1.GatewayClassReasonAccepted), status.MsgValidGatewayClass); err != nil { + if err := r.updateStatusForGatewayClass(ctx, acceptedGC, true, string(gwapiv1.GatewayClassReasonAccepted), status.MsgValidGatewayClass); err != nil { r.log.Error(err, "unable to update GatewayClass status") return reconcile.Result{}, err } @@ -491,31 +492,6 @@ func (r *gatewayAPIReconciler) processSecretRef( return nil } -func (r *gatewayAPIReconciler) gatewayClassUpdater(ctx context.Context, gc *gwapiv1.GatewayClass, accepted bool, reason, msg string) error { - if r.statusUpdater != nil { - r.statusUpdater.Send(status.Update{ - NamespacedName: types.NamespacedName{Name: gc.Name}, - Resource: &gwapiv1.GatewayClass{}, - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - gc, ok := obj.(*gwapiv1.GatewayClass) - if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) - } - - return status.SetGatewayClassAccepted(gc.DeepCopy(), accepted, reason, msg) - }), - }) - } else { - // this branch makes testing easier by not going through the status.Updater. - duplicate := status.SetGatewayClassAccepted(gc.DeepCopy(), accepted, reason, msg) - - if err := r.client.Status().Update(ctx, duplicate); err != nil && !kerrors.IsNotFound(err) { - return fmt.Errorf("error updating status of gatewayclass %s: %w", duplicate.Name, err) - } - } - return nil -} - func (r *gatewayAPIReconciler) getNamespace(ctx context.Context, name string) (*corev1.Namespace, error) { nsKey := types.NamespacedName{Name: name} ns := new(corev1.Namespace) @@ -526,50 +502,6 @@ func (r *gatewayAPIReconciler) getNamespace(ctx context.Context, name string) (* return ns, nil } -func (r *gatewayAPIReconciler) statusUpdateForGateway(ctx context.Context, gtw *gwapiv1.Gateway) { - // nil check for unit tests. - if r.statusUpdater == nil { - return - } - - // Get deployment - deploy, err := r.envoyDeploymentForGateway(ctx, gtw) - if err != nil { - r.log.Info("failed to get Deployment for gateway", - "namespace", gtw.Namespace, "name", gtw.Name) - } - - // Get service - svc, err := r.envoyServiceForGateway(ctx, gtw) - if err != nil { - r.log.Info("failed to get Service for gateway", - "namespace", gtw.Namespace, "name", gtw.Name) - } - // update accepted condition - status.UpdateGatewayStatusAcceptedCondition(gtw, true) - // update address field and programmed condition - status.UpdateGatewayStatusProgrammedCondition(gtw, svc, deploy, r.store.listNodeAddresses()...) - - key := utils.NamespacedName(gtw) - - // publish status - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(gwapiv1.Gateway), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - g, ok := obj.(*gwapiv1.Gateway) - if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) - } - gCopy := g.DeepCopy() - gCopy.Status.Conditions = gtw.Status.Conditions - gCopy.Status.Addresses = gtw.Status.Addresses - gCopy.Status.Listeners = gtw.Status.Listeners - return gCopy - }), - }) -} - func (r *gatewayAPIReconciler) findReferenceGrant(ctx context.Context, from, to ObjectKindNamespacedName) (*gwapiv1b1.ReferenceGrant, error) { refGrantList := new(gwapiv1b1.ReferenceGrantList) opts := &client.ListOptions{FieldSelector: fields.OneTermEqualSelector(targetRefGrantRouteIndex, to.kind)} @@ -923,9 +855,11 @@ func backendTCPRouteIndexFunc(rawObj client.Object) []string { return backendRefs } -// addUDPRouteIndexers adds indexing on UDPRoute, for Service objects that are -// referenced in UDPRoute objects via `.spec.rules.backendRefs`. This helps in -// querying for UDPRoutes that are affected by a particular Service CRUD. +// addUDPRouteIndexers adds indexing on UDPRoute. +// - For Gateway objects that are referenced in UDPRoute objects via `.spec.parentRefs`. This helps in +// querying for UDPRoutes that are affected by a particular Gateway CRUD. +// - For Service objects that are referenced in UDPRoute objects via `.spec.rules.backendRefs`. This helps in +// querying for UDPRoutes that are affected by a particular Service CRUD. func addUDPRouteIndexers(ctx context.Context, mgr manager.Manager) error { if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.UDPRoute{}, gatewayUDPRouteIndex, func(rawObj client.Object) []string { udpRoute := rawObj.(*gwapiv1a2.UDPRoute) @@ -1037,303 +971,6 @@ func (r *gatewayAPIReconciler) addFinalizer(ctx context.Context, gc *gwapiv1.Gat return nil } -// subscribeAndUpdateStatus subscribes to gateway API object status updates and -// writes it into the Kubernetes API Server. -func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { - // Gateway object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "gateway-status"}, r.resources.GatewayStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1.GatewayStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - // Get gateway object - gtw := new(gwapiv1.Gateway) - if err := r.client.Get(ctx, update.Key, gtw); err != nil { - r.log.Error(err, "gateway not found", "namespace", gtw.Namespace, "name", gtw.Name) - errChan <- err - return - } - // Set the updated Status and call the status update - gtw.Status = *update.Value - r.statusUpdateForGateway(ctx, gtw) - }, - ) - r.log.Info("gateway status subscriber shutting down") - }() - - // HTTPRoute object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "httproute-status"}, r.resources.HTTPRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1.HTTPRouteStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(gwapiv1.HTTPRoute), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - h, ok := obj.(*gwapiv1.HTTPRoute) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - hCopy := h.DeepCopy() - hCopy.Status.Parents = val.Parents - return hCopy - }), - }) - }, - ) - r.log.Info("httpRoute status subscriber shutting down") - }() - - // GRPCRoute object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "grpcroute-status"}, r.resources.GRPCRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1a2.GRPCRouteStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(gwapiv1a2.GRPCRoute), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - h, ok := obj.(*gwapiv1a2.GRPCRoute) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - hCopy := h.DeepCopy() - hCopy.Status.Parents = val.Parents - return hCopy - }), - }) - }, - ) - r.log.Info("grpcRoute status subscriber shutting down") - }() - - // TLSRoute object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "tlsroute-status"}, r.resources.TLSRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1a2.TLSRouteStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(gwapiv1a2.TLSRoute), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*gwapiv1a2.TLSRoute) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status.Parents = val.Parents - return tCopy - }), - }) - }, - ) - r.log.Info("tlsRoute status subscriber shutting down") - }() - - // TCPRoute object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "tcproute-status"}, r.resources.TCPRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1a2.TCPRouteStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(gwapiv1a2.TCPRoute), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*gwapiv1a2.TCPRoute) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status.Parents = val.Parents - return tCopy - }), - }) - }, - ) - r.log.Info("tcpRoute status subscriber shutting down") - }() - - // UDPRoute object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "udproute-status"}, r.resources.UDPRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1a2.UDPRouteStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(gwapiv1a2.UDPRoute), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*gwapiv1a2.UDPRoute) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status.Parents = val.Parents - return tCopy - }), - }) - }, - ) - r.log.Info("udpRoute status subscriber shutting down") - }() - - // EnvoyPatchPolicy object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "envoypatchpolicy-status"}, r.resources.EnvoyPatchPolicyStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *v1alpha1.EnvoyPatchPolicyStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(v1alpha1.EnvoyPatchPolicy), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*v1alpha1.EnvoyPatchPolicy) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status = *val - return tCopy - }), - }) - }, - ) - r.log.Info("envoyPatchPolicy status subscriber shutting down") - }() - - // ClientTrafficPolicy object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "clienttrafficpolicy-status"}, r.resources.ClientTrafficPolicyStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *v1alpha1.ClientTrafficPolicyStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(v1alpha1.ClientTrafficPolicy), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*v1alpha1.ClientTrafficPolicy) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status = *val - return tCopy - }), - }) - }, - ) - r.log.Info("clientTrafficPolicy status subscriber shutting down") - }() - - // BackendTrafficPolicy object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "backendtrafficpolicy-status"}, r.resources.BackendTrafficPolicyStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *v1alpha1.BackendTrafficPolicyStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(v1alpha1.BackendTrafficPolicy), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*v1alpha1.BackendTrafficPolicy) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status = *val - return tCopy - }), - }) - }, - ) - r.log.Info("backendTrafficPolicy status subscriber shutting down") - }() - - // SecurityPolicy object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "securitypolicy-status"}, r.resources.SecurityPolicyStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *v1alpha1.SecurityPolicyStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(v1alpha1.SecurityPolicy), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*v1alpha1.SecurityPolicy) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status = *val - return tCopy - }), - }) - }, - ) - r.log.Info("securityPolicy status subscriber shutting down") - }() -} - // watchResources watches gateway api resources. func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.Manager, c controller.Controller) error { if err := c.Watch( @@ -1525,7 +1162,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M return err } - // Watch Secret CRUDs and process affected Gateways. + // Watch Secret CRUDs and process affected EG CRs (Gateway, SecurityPolicy, more in the future). secretPredicates := []predicate.Predicate{ predicate.GenerationChangedPredicate{}, predicate.NewPredicateFuncs(r.validateSecretForReconcile), @@ -1627,6 +1264,9 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M ); err != nil { return err } + if err := addSecurityPolicyIndexers(ctx, mgr); err != nil { + return err + } r.log.Info("Watching gatewayAPI related objects") @@ -1757,3 +1397,36 @@ func (r *gatewayAPIReconciler) serviceImportCRDExists(mgr manager.Manager) bool return serviceImportFound } + +// addSecurityPolicyIndexers adds indexing on SecurityPolicy, for Secret objects that are +// referenced in SecurityPolicy objects. This helps in querying for SecurityPolicies that are +// affected by a particular Secret CRUD. +func addSecurityPolicyIndexers(ctx context.Context, mgr manager.Manager) error { + return mgr.GetFieldIndexer().IndexField(ctx, &v1alpha1.SecurityPolicy{}, secretSecurityPolicyIndex, secretSecurityPolicyIndexFunc) +} + +func secretSecurityPolicyIndexFunc(rawObj client.Object) []string { + securityPolicy := rawObj.(*v1alpha1.SecurityPolicy) + + var ( + secretReferences []gwapiv1b1.SecretObjectReference + values []string + ) + + if securityPolicy.Spec.OIDC != nil { + secretReferences = append(secretReferences, securityPolicy.Spec.OIDC.ClientSecret) + } + if securityPolicy.Spec.BasicAuth != nil { + secretReferences = append(secretReferences, securityPolicy.Spec.BasicAuth.Users) + } + + for _, reference := range secretReferences { + values = append(values, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOr(reference.Namespace, securityPolicy.Namespace), + Name: string(reference.Name), + }.String(), + ) + } + return values +} diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index 0285dedcbc4..83baf4816b0 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -21,6 +21,7 @@ import ( gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" mcsapi "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" + "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/gatewayapi" "github.com/envoyproxy/gateway/internal/provider/utils" ) @@ -137,11 +138,23 @@ func (r *gatewayAPIReconciler) validateSecretForReconcile(obj client.Object) boo return false } + if r.secretReferencedByGateway(secret) { + return true + } + + if r.secretReferencedBySecurityPolicy(secret) { + return true + } + + return false +} + +func (r *gatewayAPIReconciler) secretReferencedByGateway(secret *corev1.Secret) bool { gwList := &gwapiv1.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") + r.log.Error(err, "unable to find associated Gateways") return false } @@ -155,10 +168,21 @@ func (r *gatewayAPIReconciler) validateSecretForReconcile(obj client.Object) boo return false } } - return true } +func (r *gatewayAPIReconciler) secretReferencedBySecurityPolicy(secret *corev1.Secret) bool { + spList := &v1alpha1.SecurityPolicyList{} + if err := r.client.List(context.Background(), spList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(secretSecurityPolicyIndex, utils.NamespacedName(secret).String()), + }); err != nil { + r.log.Error(err, "unable to find associated SecurityPolicies") + return false + } + + return len(spList.Items) > 0 +} + // 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. @@ -174,7 +198,7 @@ func (r *gatewayAPIReconciler) validateServiceForReconcile(obj client.Object) bo // Check if the Service belongs to a Gateway, if so, update the Gateway status. gtw := r.findOwningGateway(ctx, labels) if gtw != nil { - r.statusUpdateForGateway(ctx, gtw) + r.updateStatusForGateway(ctx, gtw) return false } @@ -185,7 +209,7 @@ func (r *gatewayAPIReconciler) validateServiceForReconcile(obj client.Object) bo if res != nil && len(res.Gateways) > 0 { for _, gw := range res.Gateways { gw := gw - r.statusUpdateForGateway(ctx, gw) + r.updateStatusForGateway(ctx, gw) } } @@ -309,7 +333,7 @@ func (r *gatewayAPIReconciler) validateDeploymentForReconcile(obj client.Object) // Check if the deployment belongs to a Gateway, if so, update the Gateway status. gtw := r.findOwningGateway(ctx, labels) if gtw != nil { - r.statusUpdateForGateway(ctx, gtw) + r.updateStatusForGateway(ctx, gtw) return false } } @@ -321,7 +345,7 @@ func (r *gatewayAPIReconciler) validateDeploymentForReconcile(obj client.Object) if res != nil && len(res.Gateways) > 0 { for _, gw := range res.Gateways { gw := gw - r.statusUpdateForGateway(ctx, gw) + r.updateStatusForGateway(ctx, gw) } } return false diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go index 1f36f3c3f75..cd9582ccb3f 100644 --- a/internal/provider/kubernetes/predicates_test.go +++ b/internal/provider/kubernetes/predicates_test.go @@ -13,10 +13,12 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/envoygateway" @@ -211,7 +213,67 @@ func TestValidateSecretForReconcile(t *testing.T) { expect: false, }, { - name: "gateway does not exist", + name: "references SecurityPolicy OIDC", + configs: []client.Object{ + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc"), + &v1alpha1.SecurityPolicy{ + ObjectMeta: v1.ObjectMeta{ + Name: "oidc", + }, + Spec: v1alpha1.SecurityPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Kind: "Gateway", + Name: "scheduled-status-test", + }, + }, + OIDC: &v1alpha1.OIDC{ + Provider: v1alpha1.OIDCProvider{ + Issuer: "https://accounts.google.com", + AuthorizationEndpoint: ptr.To("https://accounts.google.com/o/oauth2/v2/auth"), + TokenEndpoint: ptr.To("https://oauth2.googleapis.com/token"), + }, + ClientID: "client-id", + ClientSecret: gwapiv1b1.SecretObjectReference{ + Name: "secret", + }, + }, + }, + }, + }, + secret: test.GetSecret(types.NamespacedName{Name: "secret"}), + expect: true, + }, + { + name: "references SecurityPolicy Basic Auth", + configs: []client.Object{ + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc"), + &v1alpha1.SecurityPolicy{ + ObjectMeta: v1.ObjectMeta{ + Name: "basic-auth", + }, + Spec: v1alpha1.SecurityPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Kind: "Gateway", + Name: "scheduled-status-test", + }, + }, + BasicAuth: &v1alpha1.BasicAuth{ + Users: gwapiv1b1.SecretObjectReference{ + Name: "secret", + }, + }, + }, + }, + }, + secret: test.GetSecret(types.NamespacedName{Name: "secret"}), + expect: true, + }, + { + name: "secret is not referenced by any EG CRs", configs: []client.Object{ test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), }, @@ -234,6 +296,7 @@ func TestValidateSecretForReconcile(t *testing.T) { WithScheme(envoygateway.GetScheme()). WithObjects(tc.configs...). WithIndex(&gwapiv1.Gateway{}, secretGatewayIndex, secretGatewayIndexFunc). + WithIndex(&v1alpha1.SecurityPolicy{}, secretSecurityPolicyIndex, secretSecurityPolicyIndexFunc). Build() t.Run(tc.name, func(t *testing.T) { res := r.validateSecretForReconcile(tc.secret) diff --git a/internal/provider/kubernetes/status.go b/internal/provider/kubernetes/status.go new file mode 100644 index 00000000000..83f88579c46 --- /dev/null +++ b/internal/provider/kubernetes/status.go @@ -0,0 +1,411 @@ +// 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" + "fmt" + + kerrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + + "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/message" + "github.com/envoyproxy/gateway/internal/provider/utils" + "github.com/envoyproxy/gateway/internal/status" +) + +// subscribeAndUpdateStatus subscribes to gateway API object status updates and +// writes it into the Kubernetes API Server. +func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { + // Gateway object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "gateway-status"}, + r.resources.GatewayStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1.GatewayStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + // Get gateway object + gtw := new(gwapiv1.Gateway) + if err := r.client.Get(ctx, update.Key, gtw); err != nil { + r.log.Error(err, "gateway not found", "namespace", gtw.Namespace, "name", gtw.Name) + errChan <- err + return + } + // Set the updated Status and call the status update + gtw.Status = *update.Value + r.updateStatusForGateway(ctx, gtw) + }, + ) + r.log.Info("gateway status subscriber shutting down") + }() + + // HTTPRoute object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "httproute-status"}, + r.resources.HTTPRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1.HTTPRouteStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(gwapiv1.HTTPRoute), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + h, ok := obj.(*gwapiv1.HTTPRoute) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + hCopy := h.DeepCopy() + hCopy.Status.Parents = val.Parents + return hCopy + }), + }) + }, + ) + r.log.Info("httpRoute status subscriber shutting down") + }() + + // GRPCRoute object status updater + go func() { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "grpcroute-status"}, r.resources.GRPCRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1a2.GRPCRouteStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(gwapiv1a2.GRPCRoute), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + h, ok := obj.(*gwapiv1a2.GRPCRoute) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + hCopy := h.DeepCopy() + hCopy.Status.Parents = val.Parents + return hCopy + }), + }) + }, + ) + r.log.Info("grpcRoute status subscriber shutting down") + }() + + // TLSRoute object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "tlsroute-status"}, + r.resources.TLSRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1a2.TLSRouteStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(gwapiv1a2.TLSRoute), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*gwapiv1a2.TLSRoute) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status.Parents = val.Parents + return tCopy + }), + }) + }, + ) + r.log.Info("tlsRoute status subscriber shutting down") + }() + + // TCPRoute object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "tcproute-status"}, + r.resources.TCPRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1a2.TCPRouteStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(gwapiv1a2.TCPRoute), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*gwapiv1a2.TCPRoute) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status.Parents = val.Parents + return tCopy + }), + }) + }, + ) + r.log.Info("tcpRoute status subscriber shutting down") + }() + + // UDPRoute object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "udproute-status"}, + r.resources.UDPRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1a2.UDPRouteStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(gwapiv1a2.UDPRoute), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*gwapiv1a2.UDPRoute) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status.Parents = val.Parents + return tCopy + }), + }) + }, + ) + r.log.Info("udpRoute status subscriber shutting down") + }() + + // EnvoyPatchPolicy object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "envoypatchpolicy-status"}, + r.resources.EnvoyPatchPolicyStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *v1alpha1.EnvoyPatchPolicyStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(v1alpha1.EnvoyPatchPolicy), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*v1alpha1.EnvoyPatchPolicy) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status = *val + return tCopy + }), + }) + }, + ) + r.log.Info("envoyPatchPolicy status subscriber shutting down") + }() + + // ClientTrafficPolicy object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "clienttrafficpolicy-status"}, + r.resources.ClientTrafficPolicyStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *v1alpha1.ClientTrafficPolicyStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(v1alpha1.ClientTrafficPolicy), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*v1alpha1.ClientTrafficPolicy) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status = *val + return tCopy + }), + }) + }, + ) + r.log.Info("clientTrafficPolicy status subscriber shutting down") + }() + + // BackendTrafficPolicy object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "backendtrafficpolicy-status"}, + r.resources.BackendTrafficPolicyStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *v1alpha1.BackendTrafficPolicyStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(v1alpha1.BackendTrafficPolicy), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*v1alpha1.BackendTrafficPolicy) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status = *val + return tCopy + }), + }) + }, + ) + r.log.Info("backendTrafficPolicy status subscriber shutting down") + }() + + // SecurityPolicy object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "securitypolicy-status"}, + r.resources.SecurityPolicyStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *v1alpha1.SecurityPolicyStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(v1alpha1.SecurityPolicy), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*v1alpha1.SecurityPolicy) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status = *val + return tCopy + }), + }) + }, + ) + r.log.Info("securityPolicy status subscriber shutting down") + }() +} + +func (r *gatewayAPIReconciler) updateStatusForGateway(ctx context.Context, gtw *gwapiv1.Gateway) { + // nil check for unit tests. + if r.statusUpdater == nil { + return + } + + // Get deployment + deploy, err := r.envoyDeploymentForGateway(ctx, gtw) + if err != nil { + r.log.Info("failed to get Deployment for gateway", + "namespace", gtw.Namespace, "name", gtw.Name) + } + + // Get service + svc, err := r.envoyServiceForGateway(ctx, gtw) + if err != nil { + r.log.Info("failed to get Service for gateway", + "namespace", gtw.Namespace, "name", gtw.Name) + } + // update accepted condition + status.UpdateGatewayStatusAcceptedCondition(gtw, true) + // update address field and programmed condition + status.UpdateGatewayStatusProgrammedCondition(gtw, svc, deploy, r.store.listNodeAddresses()...) + + key := utils.NamespacedName(gtw) + + // publish status + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(gwapiv1.Gateway), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + g, ok := obj.(*gwapiv1.Gateway) + if !ok { + panic(fmt.Sprintf("unsupported object type %T", obj)) + } + gCopy := g.DeepCopy() + gCopy.Status.Conditions = gtw.Status.Conditions + gCopy.Status.Addresses = gtw.Status.Addresses + gCopy.Status.Listeners = gtw.Status.Listeners + return gCopy + }), + }) +} + +func (r *gatewayAPIReconciler) updateStatusForGatewayClass( + ctx context.Context, + gc *gwapiv1.GatewayClass, + accepted bool, + reason, + msg string) error { + if r.statusUpdater != nil { + r.statusUpdater.Send(status.Update{ + NamespacedName: types.NamespacedName{Name: gc.Name}, + Resource: &gwapiv1.GatewayClass{}, + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + gc, ok := obj.(*gwapiv1.GatewayClass) + if !ok { + panic(fmt.Sprintf("unsupported object type %T", obj)) + } + + return status.SetGatewayClassAccepted(gc.DeepCopy(), accepted, reason, msg) + }), + }) + } else { + // this branch makes testing easier by not going through the status.Updater. + duplicate := status.SetGatewayClassAccepted(gc.DeepCopy(), accepted, reason, msg) + + if err := r.client.Status().Update(ctx, duplicate); err != nil && !kerrors.IsNotFound(err) { + return fmt.Errorf("error updating status of gatewayclass %s: %w", duplicate.Name, err) + } + } + return nil +} From 0bd88fe1a376c3f84f6c7ac2d3d7c4a140604bf0 Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Sat, 27 Jan 2024 07:48:09 +0800 Subject: [PATCH 2/3] api: add compressor/decompressor support (#2474) * Add API for compressor Signed-off-by: He Jie Xu * update Signed-off-by: He Jie Xu * update Signed-off-by: He Jie Xu * update Signed-off-by: He Jie Xu * update doc Signed-off-by: He Jie Xu * generate manifests Signed-off-by: He Jie Xu * generate Signed-off-by: He Jie Xu * address comments Signed-off-by: He Jie Xu * generate manifests Signed-off-by: He Jie Xu * address comments Signed-off-by: He Jie Xu * generate Signed-off-by: He Jie Xu * update Signed-off-by: He Jie Xu * generate Signed-off-by: He Jie Xu * update comments Signed-off-by: He Jie Xu * generate Signed-off-by: He Jie Xu * address comments Signed-off-by: He Jie Xu * generate Signed-off-by: He Jie Xu * address comments Signed-off-by: He Jie Xu * generate Signed-off-by: He Jie Xu * generate again Signed-off-by: He Jie Xu --------- Signed-off-by: He Jie Xu --- api/v1alpha1/backendtrafficpolicy_types.go | 5 ++ api/v1alpha1/compression_types.go | 31 +++++++++++++ api/v1alpha1/zz_generated.deepcopy.go | 46 +++++++++++++++++++ ....envoyproxy.io_backendtrafficpolicies.yaml | 19 ++++++++ site/content/en/latest/api/extension_types.md | 38 +++++++++++++++ 5 files changed, 139 insertions(+) create mode 100644 api/v1alpha1/compression_types.go diff --git a/api/v1alpha1/backendtrafficpolicy_types.go b/api/v1alpha1/backendtrafficpolicy_types.go index 7ce639cc3b2..163563acb36 100644 --- a/api/v1alpha1/backendtrafficpolicy_types.go +++ b/api/v1alpha1/backendtrafficpolicy_types.go @@ -86,6 +86,11 @@ type BackendTrafficPolicySpec struct { // // +optional Timeout *Timeout `json:"timeout,omitempty"` + + // The compression config for the http streams. + // + // +optional + Compression []*Compression `json:"compression,omitempty"` } // BackendTrafficPolicyStatus defines the state of BackendTrafficPolicy diff --git a/api/v1alpha1/compression_types.go b/api/v1alpha1/compression_types.go new file mode 100644 index 00000000000..37c0ec8587b --- /dev/null +++ b/api/v1alpha1/compression_types.go @@ -0,0 +1,31 @@ +// 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 v1alpha1 + +// CompressorType defines the types of compressor library supported by Envoy Gateway. +// +// +kubebuilder:validation:Enum=Gzip +type CompressorType string + +// GzipCompressor defines the config for the Gzip compressor. +// The default values can be found here: +// https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/compression/gzip/compressor/v3/gzip.proto#extension-envoy-compression-gzip-compressor +type GzipCompressor struct { +} + +// Compression defines the config of enabling compression. +// This can help reduce the bandwidth at the expense of higher CPU. +type Compression struct { + // CompressorType defines the compressor type to use for compression. + // + // +required + Type CompressorType `json:"type"` + + // The configuration for GZIP compressor. + // + // +optional + Gzip *GzipCompressor `json:"gzip,omitempty"` +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index ff23045bdab..fb28e836931 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -121,6 +121,17 @@ func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec) *out = new(Timeout) (*in).DeepCopyInto(*out) } + if in.Compression != nil { + in, out := &in.Compression, &out.Compression + *out = make([]*Compression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Compression) + (*in).DeepCopyInto(*out) + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTrafficPolicySpec. @@ -413,6 +424,26 @@ func (in *ClientValidationContext) DeepCopy() *ClientValidationContext { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Compression) DeepCopyInto(out *Compression) { + *out = *in + if in.Gzip != nil { + in, out := &in.Gzip, &out.Gzip + *out = new(GzipCompressor) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Compression. +func (in *Compression) DeepCopy() *Compression { + if in == nil { + return nil + } + out := new(Compression) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConsistentHash) DeepCopyInto(out *ConsistentHash) { *out = *in @@ -1402,6 +1433,21 @@ func (in *GroupVersionKind) DeepCopy() *GroupVersionKind { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GzipCompressor) DeepCopyInto(out *GzipCompressor) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GzipCompressor. +func (in *GzipCompressor) DeepCopy() *GzipCompressor { + if in == nil { + return nil + } + out := new(GzipCompressor) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTP1Settings) DeepCopyInto(out *HTTP1Settings) { *out = *in diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index 3ba103df393..2e92a810713 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -77,6 +77,25 @@ spec: minimum: 0 type: integer type: object + compression: + description: The compression config for the http streams. + items: + description: Compression defines the config of enabling compression. + This can help reduce the bandwidth at the expense of higher CPU. + properties: + gzip: + description: The configuration for GZIP compressor. + type: object + type: + description: CompressorType defines the compressor type to use + for compression. + enum: + - Gzip + type: string + required: + - type + type: object + type: array faultInjection: description: FaultInjection defines the fault injection policy to be applied. This configuration can be used to inject delays and diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 32ef8e9f87c..f29c506c28b 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -91,6 +91,7 @@ _Appears in:_ | `faultInjection` _[FaultInjection](#faultinjection)_ | FaultInjection defines the fault injection policy to be applied. This configuration can be used to inject delays and abort requests to mimic failure scenarios such as service failures and overloads | | `circuitBreaker` _[CircuitBreaker](#circuitbreaker)_ | Circuit Breaker settings for the upstream connections and requests. If not set, circuit breakers will be enabled with the default thresholds | | `timeout` _[Timeout](#timeout)_ | Timeout settings for the backend connections. | +| `compression` _[Compression](#compression) array_ | The compression config for the http streams. | @@ -244,6 +245,32 @@ _Appears in:_ References to a resource in different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. | +#### Compression + + + +Compression defines the config of enabling compression. This can help reduce the bandwidth at the expense of higher CPU. + +_Appears in:_ +- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) + +| Field | Description | +| --- | --- | +| `type` _[CompressorType](#compressortype)_ | CompressorType defines the compressor type to use for compression. | +| `gzip` _[GzipCompressor](#gzipcompressor)_ | The configuration for GZIP compressor. | + + +#### CompressorType + +_Underlying type:_ `string` + +CompressorType defines the types of compressor library supported by Envoy Gateway. + +_Appears in:_ +- [Compression](#compression) + + + #### ConsistentHash @@ -933,6 +960,17 @@ _Appears in:_ | `kind` _string_ | | +#### GzipCompressor + + + +GzipCompressor defines the config for the Gzip compressor. The default values can be found here: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/compression/gzip/compressor/v3/gzip.proto#extension-envoy-compression-gzip-compressor + +_Appears in:_ +- [Compression](#compression) + + + #### HTTP1Settings From 2feae69705253ef2e1a1abd04a380a0275c64b11 Mon Sep 17 00:00:00 2001 From: zirain Date: Sat, 27 Jan 2024 08:14:41 +0800 Subject: [PATCH 3/3] chore: fix lint (#2514) Signed-off-by: zirain --- internal/provider/kubernetes/predicates_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go index cd9582ccb3f..9760e16308d 100644 --- a/internal/provider/kubernetes/predicates_test.go +++ b/internal/provider/kubernetes/predicates_test.go @@ -218,7 +218,7 @@ func TestValidateSecretForReconcile(t *testing.T) { test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc"), &v1alpha1.SecurityPolicy{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "oidc", }, Spec: v1alpha1.SecurityPolicySpec{ @@ -251,7 +251,7 @@ func TestValidateSecretForReconcile(t *testing.T) { test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc"), &v1alpha1.SecurityPolicy{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "basic-auth", }, Spec: v1alpha1.SecurityPolicySpec{