diff --git a/internal/gatewayapi/backendtlspolicy.go b/internal/gatewayapi/backendtlspolicy.go index a1ee9045bd7..abfc5e1c470 100644 --- a/internal/gatewayapi/backendtlspolicy.go +++ b/internal/gatewayapi/backendtlspolicy.go @@ -75,6 +75,7 @@ func localPolicyTargetReferenceWithSectionNameToKey(ns string, targetRef gwapiv1 // applyBackendTLSSetting processes TLS settings from Backend resource, BackendTLSPolicy, and EnvoyProxy resource. // It merges the TLS settings from these resources and returns the final TLS config to be applied to the upstream cluster. func (t *Translator) applyBackendTLSSetting( + translatorContext *TranslatorContext, backendRef gwapiv1.BackendObjectReference, backendNamespace string, parent gwapiv1.ParentReference, @@ -93,19 +94,20 @@ func (t *Translator) applyBackendTLSSetting( // If the backendRef is a Backend resource, we need to check if it has TLS settings. if KindDerefOr(backendRef.Kind, resource.KindService) == egv1a1.KindBackend { - backend := resources.GetBackend(backendNamespace, string(backendRef.Name)) + backend := translatorContext.GetBackend(backendNamespace, string(backendRef.Name)) if backend == nil { return nil, fmt.Errorf("backend %s not found", backendRef.Name) } if backend.Spec.TLS != nil { // Get the server certificate validation settings from Backend resource. - if backendValidationTLSConfig, err = t.processServerValidationTLSSettings(backend, resources); err != nil { + if backendValidationTLSConfig, err = t.processServerValidationTLSSettings(translatorContext, backend); err != nil { return nil, err } // Get the client certificate and common TLS settings from Backend resource. if backend.Spec.TLS.BackendTLSConfig != nil { - if backendClientTLSConfig, err = t.processClientTLSSettings(resources, backend.Spec.TLS.BackendTLSConfig, backend.Namespace, backend.Name, false); err != nil { + if backendClientTLSConfig, err = t.processClientTLSSettings(translatorContext, + backend.Spec.TLS.BackendTLSConfig, backend.Namespace, backend.Name, false); err != nil { return nil, err } } @@ -113,7 +115,7 @@ func (t *Translator) applyBackendTLSSetting( } // Get the backend certificate validation settings from BackendTLSPolicy. - if btpValidationTLSConfig, err = t.processBackendTLSPolicy(backendRef, backendNamespace, parent, resources); err != nil { + if btpValidationTLSConfig, err = t.processBackendTLSPolicy(translatorContext, backendRef, backendNamespace, parent, resources); err != nil { return nil, err } @@ -132,7 +134,8 @@ func (t *Translator) applyBackendTLSSetting( // Get the client certificate and common TLS settings from EnvoyProxy resource. if envoyProxy != nil && envoyProxy.Spec.BackendTLS != nil { - if envoyProxyClientTLSConfig, err = t.processClientTLSSettings(resources, envoyProxy.Spec.BackendTLS, envoyProxy.Namespace, envoyProxy.Name, true); err != nil { + if envoyProxyClientTLSConfig, err = t.processClientTLSSettings(translatorContext, + envoyProxy.Spec.BackendTLS, envoyProxy.Namespace, envoyProxy.Name, true); err != nil { return nil, err } } @@ -238,8 +241,8 @@ func mergeClientTLSConfigs( } func (t *Translator) processServerValidationTLSSettings( + translatorContext *TranslatorContext, backend *egv1a1.Backend, - resources *resource.Resources, ) (*ir.TLSUpstreamConfig, error) { tlsConfig := &ir.TLSUpstreamConfig{ InsecureSkipVerify: ptr.Deref(backend.Spec.TLS.InsecureSkipVerify, false), @@ -257,7 +260,7 @@ func (t *Translator) processServerValidationTLSSettings( Name: fmt.Sprintf("%s/%s-ca", backend.Name, backend.Namespace), } } else if len(backend.Spec.TLS.CACertificateRefs) > 0 { - caCert, err := getCaCertsFromCARefs(backend.Namespace, backend.Spec.TLS.CACertificateRefs, resources) + caCert, err := getCaCertsFromCARefs(translatorContext, backend.Namespace, backend.Spec.TLS.CACertificateRefs) if err != nil { return nil, err } @@ -271,17 +274,18 @@ func (t *Translator) processServerValidationTLSSettings( } func (t *Translator) processBackendTLSPolicy( + translatorContext *TranslatorContext, backendRef gwapiv1.BackendObjectReference, backendNamespace string, parent gwapiv1.ParentReference, resources *resource.Resources, ) (*ir.TLSUpstreamConfig, error) { - policy := getBackendTLSPolicy(resources.BackendTLSPolicies, backendRef, backendNamespace, resources) + policy := getBackendTLSPolicy(translatorContext, resources.BackendTLSPolicies, backendRef, backendNamespace) if policy == nil { return nil, nil } - tlsBundle, err := getBackendTLSBundle(policy, resources) + tlsBundle, err := getBackendTLSBundle(translatorContext, policy) ancestorRefs := getAncestorRefs(policy) ancestorRefs = append(ancestorRefs, &parent) @@ -326,7 +330,12 @@ func (t *Translator) processBackendTLSPolicy( return tlsBundle, nil } -func (t *Translator) processClientTLSSettings(resources *resource.Resources, clientTLS *egv1a1.BackendTLSConfig, ownerNs, ownerName string, fromEnvoyProxy bool) (*ir.TLSConfig, error) { +func (t *Translator) processClientTLSSettings( + translatorContext *TranslatorContext, + clientTLS *egv1a1.BackendTLSConfig, + ownerNs, ownerName string, + fromEnvoyProxy bool, +) (*ir.TLSConfig, error) { tlsConfig := &ir.TLSConfig{} if len(clientTLS.Ciphers) > 0 { @@ -365,7 +374,7 @@ func (t *Translator) processClientTLSSettings(resources *resource.Resources, cli err = fmt.Errorf("ClientCertificateRef Secret is not located in the same namespace as %s. Secret namespace: %s does not match %s namespace: %s", ownerResource, ns, ownerResource, ownerNs) return tlsConfig, err } - secret := resources.GetSecret(ns, string(clientTLS.ClientCertificateRef.Name)) + secret := translatorContext.GetSecret(ns, string(clientTLS.ClientCertificateRef.Name)) if secret == nil { err = fmt.Errorf( "failed to locate TLS secret for client auth: %s specified in %s %s", @@ -405,13 +414,13 @@ func backendTLSTargetMatched(policy *gwapiv1.BackendTLSPolicy, target gwapiv1.Lo } func getBackendTLSPolicy( + translatorContext *TranslatorContext, policies []*gwapiv1.BackendTLSPolicy, backendRef gwapiv1.BackendObjectReference, backendNamespace string, - resources *resource.Resources, ) *gwapiv1.BackendTLSPolicy { // SectionName is port number for EG Backend object - target := getTargetBackendReference(backendRef, backendNamespace, resources) + target := getTargetBackendReference(translatorContext, backendRef, backendNamespace) for _, policy := range policies { if backendTLSTargetMatched(policy, target, backendNamespace) { return policy @@ -420,7 +429,7 @@ func getBackendTLSPolicy( return nil } -func getBackendTLSBundle(backendTLSPolicy *gwapiv1.BackendTLSPolicy, resources *resource.Resources) (*ir.TLSUpstreamConfig, error) { +func getBackendTLSBundle(translatorContext *TranslatorContext, backendTLSPolicy *gwapiv1.BackendTLSPolicy) (*ir.TLSUpstreamConfig, error) { // Translate SubjectAltNames from gwapiv1a3 to ir subjectAltNames := make([]ir.SubjectAltName, 0, len(backendTLSPolicy.Spec.Validation.SubjectAltNames)) for _, san := range backendTLSPolicy.Spec.Validation.SubjectAltNames { @@ -448,7 +457,8 @@ func getBackendTLSBundle(backendTLSPolicy *gwapiv1.BackendTLSPolicy, resources * return tlsBundle, nil } - caCert, err := getCaCertsFromCARefs(backendTLSPolicy.Namespace, backendTLSPolicy.Spec.Validation.CACertificateRefs, resources) + caCert, err := getCaCertsFromCARefs(translatorContext, + backendTLSPolicy.Namespace, backendTLSPolicy.Spec.Validation.CACertificateRefs) if err != nil { return nil, err } @@ -459,14 +469,18 @@ func getBackendTLSBundle(backendTLSPolicy *gwapiv1.BackendTLSPolicy, resources * return tlsBundle, nil } -func getCaCertsFromCARefs(namespace string, caCertificates []gwapiv1.LocalObjectReference, resources *resource.Resources) ([]byte, error) { +func getCaCertsFromCARefs( + translatorContext *TranslatorContext, + namespace string, + caCertificates []gwapiv1.LocalObjectReference, +) ([]byte, error) { ca := "" for _, caRef := range caCertificates { kind := string(caRef.Kind) switch kind { case resource.KindConfigMap: - cm := resources.GetConfigMap(namespace, string(caRef.Name)) + cm := translatorContext.GetConfigMap(namespace, string(caRef.Name)) if cm != nil { if crt, dataOk := getOrFirstFromData(cm.Data, caCertKey); dataOk { if ca != "" { @@ -480,7 +494,7 @@ func getCaCertsFromCARefs(namespace string, caCertificates []gwapiv1.LocalObject return nil, fmt.Errorf("configmap %s not found in namespace %s", caRef.Name, namespace) } case resource.KindSecret: - secret := resources.GetSecret(namespace, string(caRef.Name)) + secret := translatorContext.GetSecret(namespace, string(caRef.Name)) if secret != nil { if crt, dataOk := getOrFirstFromData(secret.Data, caCertKey); dataOk { if ca != "" { @@ -494,7 +508,7 @@ func getCaCertsFromCARefs(namespace string, caCertificates []gwapiv1.LocalObject return nil, fmt.Errorf("secret %s not found in namespace %s", caRef.Name, namespace) } case resource.KindClusterTrustBundle: - ctb := resources.GetClusterTrustBundle(string(caRef.Name)) + ctb := translatorContext.GetClusterTrustBundle(string(caRef.Name)) if ctb != nil { if ca != "" { ca += "\n" diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go index a339d3b8c8d..dba48bb6a9e 100644 --- a/internal/gatewayapi/backendtrafficpolicy.go +++ b/internal/gatewayapi/backendtrafficpolicy.go @@ -33,7 +33,9 @@ const ( MaxConsistentHashTableSize = 5000011 // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-maglevlbconfig ) -func (t *Translator) ProcessBackendTrafficPolicies(resources *resource.Resources, +func (t *Translator) ProcessBackendTrafficPolicies( + translatorContext *TranslatorContext, + resources *resource.Resources, gateways []*GatewayContext, routes []RouteContext, xdsIR resource.XdsIRMap, @@ -104,7 +106,7 @@ func (t *Translator) ProcessBackendTrafficPolicies(resources *resource.Resources res = append(res, policy) } - t.processBackendTrafficPolicyForRoute(resources, xdsIR, + t.processBackendTrafficPolicyForRoute(translatorContext, xdsIR, routeMap, gatewayRouteMap, gatewayPolicyMerged, gatewayPolicyMap, policy, currTarget) } } @@ -124,7 +126,7 @@ func (t *Translator) ProcessBackendTrafficPolicies(resources *resource.Resources res = append(res, policy) } - t.processBackendTrafficPolicyForRoute(resources, xdsIR, + t.processBackendTrafficPolicyForRoute(translatorContext, xdsIR, routeMap, gatewayRouteMap, gatewayPolicyMerged, gatewayPolicyMap, policy, currTarget) } } @@ -143,7 +145,7 @@ func (t *Translator) ProcessBackendTrafficPolicies(resources *resource.Resources handledPolicies[policyName] = policy res = append(res, policy) } - t.processBackendTrafficPolicyForGateway(resources, xdsIR, + t.processBackendTrafficPolicyForGateway(translatorContext, xdsIR, gatewayMap, gatewayRouteMap, gatewayPolicyMerged, policy, currTarget) } } @@ -162,7 +164,7 @@ func (t *Translator) ProcessBackendTrafficPolicies(resources *resource.Resources handledPolicies[policyName] = policy res = append(res, policy) } - t.processBackendTrafficPolicyForGateway(resources, xdsIR, + t.processBackendTrafficPolicyForGateway(translatorContext, xdsIR, gatewayMap, gatewayRouteMap, gatewayPolicyMerged, policy, currTarget) } } @@ -222,7 +224,7 @@ func (t *Translator) buildGatewayPolicyMap( } func (t *Translator) processBackendTrafficPolicyForRoute( - resources *resource.Resources, + translatorContext *TranslatorContext, xdsIR resource.XdsIRMap, routeMap map[policyTargetRouteKey]*policyRouteTargetContext, gatewayRouteMap *GatewayPolicyRouteMap, @@ -298,7 +300,7 @@ func (t *Translator) processBackendTrafficPolicyForRoute( if policy.Spec.MergeType == nil { // Set conditions for translation error if it got any - if err := t.translateBackendTrafficPolicyForRoute(policy, targetedRoute, currTarget, xdsIR, resources, nil, nil); err != nil { + if err := t.translateBackendTrafficPolicyForRoute(translatorContext, policy, targetedRoute, currTarget, xdsIR, nil, nil); err != nil { status.SetTranslationErrorForPolicyAncestors(&policy.Status, ancestorRefs, t.GatewayControllerName, @@ -326,7 +328,7 @@ func (t *Translator) processBackendTrafficPolicyForRoute( gwPolicy := gatewayPolicyMap[gwMapKey] if gwPolicy == nil && listenerPolicy == nil { // not found, fall back to the current policy - if err := t.translateBackendTrafficPolicyForRoute(policy, targetedRoute, currTarget, xdsIR, resources, &gwNN, &listener.Name); err != nil { + if err := t.translateBackendTrafficPolicyForRoute(translatorContext, policy, targetedRoute, currTarget, xdsIR, &gwNN, &listener.Name); err != nil { status.SetConditionForPolicyAncestor(&policy.Status, &ancestorRef, t.GatewayControllerName, @@ -344,9 +346,9 @@ func (t *Translator) processBackendTrafficPolicyForRoute( parentPolicy = listenerPolicy } // merge with parent policy - if err := t.translateBackendTrafficPolicyForRouteWithMerge( + if err := t.translateBackendTrafficPolicyForRouteWithMerge(translatorContext, policy, parentPolicy, currTarget, gwNN, &listener.Name, - targetedRoute, xdsIR, resources, + targetedRoute, xdsIR, ); err != nil { status.SetConditionForPolicyAncestor(&policy.Status, &ancestorRef, @@ -413,7 +415,7 @@ func (t *Translator) processBackendTrafficPolicyForRoute( } func (t *Translator) processBackendTrafficPolicyForGateway( - resources *resource.Resources, + translatorContext *TranslatorContext, xdsIR resource.XdsIRMap, gatewayMap map[types.NamespacedName]*policyGatewayTargetContext, gatewayRouteMap *GatewayPolicyRouteMap, @@ -448,7 +450,7 @@ func (t *Translator) processBackendTrafficPolicyForGateway( } // Set conditions for translation error if it got any - if err := t.translateBackendTrafficPolicyForGateway(policy, currTarget, targetedGateway, xdsIR, resources); err != nil { + if err := t.translateBackendTrafficPolicyForGateway(translatorContext, policy, currTarget, targetedGateway, xdsIR); err != nil { status.SetTranslationErrorForPolicyAncestor(&policy.Status, &ancestorRef, t.GatewayControllerName, @@ -611,15 +613,15 @@ func resolveBackendTrafficPolicyRouteTargetRef( } func (t *Translator) translateBackendTrafficPolicyForRoute( + translatorContext *TranslatorContext, policy *egv1a1.BackendTrafficPolicy, route RouteContext, target gwapiv1.LocalPolicyTargetReferenceWithSectionName, xdsIR resource.XdsIRMap, - resources *resource.Resources, policyTargetGatewayNN *types.NamespacedName, policyTargetListener *gwapiv1.SectionName, ) error { - tf, errs := t.buildTrafficFeatures(policy, resources) + tf, errs := t.buildTrafficFeatures(translatorContext, policy) if tf == nil { // should not happen return nil @@ -639,10 +641,11 @@ func (t *Translator) translateBackendTrafficPolicyForRoute( } func (t *Translator) translateBackendTrafficPolicyForRouteWithMerge( + translatorContext *TranslatorContext, policy, parentPolicy *egv1a1.BackendTrafficPolicy, target gwapiv1.LocalPolicyTargetReferenceWithSectionName, policyTargetGatewayNN types.NamespacedName, policyTargetListener *gwapiv1.SectionName, route RouteContext, - xdsIR resource.XdsIRMap, resources *resource.Resources, + xdsIR resource.XdsIRMap, ) error { mergedPolicy, err := mergeBackendTrafficPolicy(policy, parentPolicy) if err != nil { @@ -650,7 +653,7 @@ func (t *Translator) translateBackendTrafficPolicyForRouteWithMerge( } // Build traffic features from the merged policy - tf, errs := t.buildTrafficFeatures(mergedPolicy, resources) + tf, errs := t.buildTrafficFeatures(translatorContext, mergedPolicy) if tf == nil { // should not happen return nil @@ -665,8 +668,8 @@ func (t *Translator) translateBackendTrafficPolicyForRouteWithMerge( // 2. Only gateway policy has rate limits - preserve gateway policy's rule names // 3. Only route policy has rate limits - use route policy's rule names (default behavior) if policy.Spec.RateLimit != nil && parentPolicy.Spec.RateLimit != nil { - tfGW, _ := t.buildTrafficFeatures(parentPolicy, resources) - tfRoute, _ := t.buildTrafficFeatures(policy, resources) + tfGW, _ := t.buildTrafficFeatures(translatorContext, parentPolicy) + tfRoute, _ := t.buildTrafficFeatures(translatorContext, policy) if tfGW != nil && tfRoute != nil && tfGW.RateLimit != nil && tfRoute.RateLimit != nil { @@ -680,7 +683,7 @@ func (t *Translator) translateBackendTrafficPolicyForRouteWithMerge( } } else if policy.Spec.RateLimit == nil && parentPolicy.Spec.RateLimit != nil { // Case 2: Only gateway policy has rate limits - preserve gateway policy's rule names - tfGW, _ := t.buildTrafficFeatures(parentPolicy, resources) + tfGW, _ := t.buildTrafficFeatures(translatorContext, parentPolicy) if tfGW != nil && tfGW.RateLimit != nil { // Use the gateway policy's rate limit with its original rule names tf.RateLimit = tfGW.RateLimit @@ -814,7 +817,7 @@ func mergeBackendTrafficPolicy(routePolicy, gwPolicy *egv1a1.BackendTrafficPolic return utils.Merge[*egv1a1.BackendTrafficPolicy](gwPolicy, routePolicy, *routePolicy.Spec.MergeType) } -func (t *Translator) buildTrafficFeatures(policy *egv1a1.BackendTrafficPolicy, resources *resource.Resources) (*ir.TrafficFeatures, error) { +func (t *Translator) buildTrafficFeatures(translatorContext *TranslatorContext, policy *egv1a1.BackendTrafficPolicy) (*ir.TrafficFeatures, error) { var ( rl *ir.RateLimit lb *ir.LoadBalancer @@ -879,7 +882,7 @@ func (t *Translator) buildTrafficFeatures(policy *egv1a1.BackendTrafficPolicy, r errs = errors.Join(errs, err) } - if ro, err = buildResponseOverride(policy, resources); err != nil { + if ro, err = buildResponseOverride(translatorContext, policy); err != nil { err = perr.WithMessage(err, "ResponseOverride") errs = errors.Join(errs, err) } @@ -916,10 +919,11 @@ func (t *Translator) buildTrafficFeatures(policy *egv1a1.BackendTrafficPolicy, r } func (t *Translator) translateBackendTrafficPolicyForGateway( + translatorContext *TranslatorContext, policy *egv1a1.BackendTrafficPolicy, target gwapiv1.LocalPolicyTargetReferenceWithSectionName, - gateway *GatewayContext, xdsIR resource.XdsIRMap, resources *resource.Resources, + gateway *GatewayContext, xdsIR resource.XdsIRMap, ) error { - tf, errs := t.buildTrafficFeatures(policy, resources) + tf, errs := t.buildTrafficFeatures(translatorContext, policy) if tf == nil { // should not happen return errs @@ -1402,7 +1406,7 @@ func buildRequestBuffer(spec *egv1a1.RequestBuffer) (*ir.RequestBuffer, error) { }, nil } -func buildResponseOverride(policy *egv1a1.BackendTrafficPolicy, resources *resource.Resources) (*ir.ResponseOverride, error) { +func buildResponseOverride(translatorContext *TranslatorContext, policy *egv1a1.BackendTrafficPolicy) (*ir.ResponseOverride, error) { if len(policy.Spec.ResponseOverride) == 0 { return nil, nil } @@ -1463,7 +1467,7 @@ func buildResponseOverride(policy *egv1a1.BackendTrafficPolicy, resources *resou } var err error - response.Body, err = getCustomResponseBody(ro.Response.Body, resources, policy.Namespace) + response.Body, err = getCustomResponseBody(translatorContext, ro.Response.Body, policy.Namespace) if err != nil { return nil, err } @@ -1511,9 +1515,13 @@ func checkResponseBodySize(b []byte) error { return nil } -func getCustomResponseBody(body *egv1a1.CustomResponseBody, resources *resource.Resources, policyNs string) ([]byte, error) { +func getCustomResponseBody( + translatorContext *TranslatorContext, + body *egv1a1.CustomResponseBody, + policyNs string, +) ([]byte, error) { if body != nil && body.Type != nil && *body.Type == egv1a1.ResponseValueTypeValueRef { - cm := resources.GetConfigMap(policyNs, string(body.ValueRef.Name)) + cm := translatorContext.GetConfigMap(policyNs, string(body.ValueRef.Name)) if cm != nil { b, dataOk := cm.Data["response.body"] switch { diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index 9d50b627285..55a8006a5c4 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -37,6 +37,7 @@ func hasSectionName(target *gwapiv1.LocalPolicyTargetReferenceWithSectionName) b } func (t *Translator) ProcessClientTrafficPolicies( + translatorContext *TranslatorContext, resources *resource.Resources, gateways []*GatewayContext, xdsIR resource.XdsIRMap, @@ -136,7 +137,7 @@ func (t *Translator) ProcessClientTrafficPolicies( if string(l.Name) == section { err = validatePortOverlapForClientTrafficPolicy(l, gwXdsIR, false) if err == nil { - err = t.translateClientTrafficPolicyForListener(policy, l, xdsIR, infraIR, resources) + err = t.translateClientTrafficPolicyForListener(translatorContext, policy, l, xdsIR, infraIR, resources) } break } @@ -253,7 +254,7 @@ func (t *Translator) ProcessClientTrafficPolicies( gwXdsIR := xdsIR[irKey] if err := validatePortOverlapForClientTrafficPolicy(l, gwXdsIR, true); err != nil { errs = errors.Join(errs, err) - } else if err := t.translateClientTrafficPolicyForListener(policy, l, xdsIR, infraIR, resources); err != nil { + } else if err := t.translateClientTrafficPolicyForListener(translatorContext, policy, l, xdsIR, infraIR, resources); err != nil { errs = errors.Join(errs, err) } } @@ -355,7 +356,9 @@ func validatePortOverlapForClientTrafficPolicy(l *ListenerContext, xds *ir.Xds, return nil } -func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.ClientTrafficPolicy, l *ListenerContext, +func (t *Translator) translateClientTrafficPolicyForListener( + translatorContext *TranslatorContext, + policy *egv1a1.ClientTrafficPolicy, l *ListenerContext, xdsIR resource.XdsIRMap, infraIR resource.InfraIRMap, resources *resource.Resources, ) error { // Find IR @@ -476,7 +479,7 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie translateHealthCheckSettings(policy.Spec.HealthCheck, httpIR) // Translate TLS parameters - tlsConfig, err = t.buildListenerTLSParameters(policy, httpIR.TLS, resources) + tlsConfig, err = t.buildListenerTLSParameters(translatorContext, policy, httpIR.TLS, resources) if err != nil { err = perr.WithMessage(err, "TLS") errs = errors.Join(errs, err) @@ -511,7 +514,7 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie if tcpIR != nil { // Translate TLS parameters - tlsConfig, err = t.buildListenerTLSParameters(policy, tcpIR.TLS, resources) + tlsConfig, err = t.buildListenerTLSParameters(translatorContext, policy, tcpIR.TLS, resources) if err != nil { err = perr.WithMessage(err, "TLS") errs = errors.Join(errs, err) @@ -756,7 +759,9 @@ func translateHealthCheckSettings(healthCheckSettings *egv1a1.HealthCheckSetting httpIR.HealthCheck = (*ir.HealthCheckSettings)(healthCheckSettings) } -func (t *Translator) buildListenerTLSParameters(policy *egv1a1.ClientTrafficPolicy, +func (t *Translator) buildListenerTLSParameters( + translatorContext *TranslatorContext, + policy *egv1a1.ClientTrafficPolicy, irTLSConfig *ir.TLSConfig, resources *resource.Resources, ) (*ir.TLSConfig, error) { // Return if this listener isn't a TLS listener. There has to be @@ -813,7 +818,7 @@ func (t *Translator) buildListenerTLSParameters(policy *egv1a1.ClientTrafficPoli } for _, caCertRef := range tlsParams.ClientValidation.CACertificateRefs { - caCertBytes, err := t.validateAndGetDataAtKeyInRef(caCertRef, caCertKey, resources, from) + caCertBytes, err := t.validateAndGetDataAtKeyInRef(translatorContext, caCertRef, caCertKey, resources, from) if err != nil { return irTLSConfig, fmt.Errorf("failed to get certificate from ref: %w", err) } @@ -834,7 +839,7 @@ func (t *Translator) buildListenerTLSParameters(policy *egv1a1.ClientTrafficPoli if tlsParams.ClientValidation.Crl != nil { for _, crlRef := range tlsParams.ClientValidation.Crl.Refs { - crlBytes, err := t.validateAndGetDataAtKeyInRef(crlRef, crlKey, resources, from) + crlBytes, err := t.validateAndGetDataAtKeyInRef(translatorContext, crlRef, crlKey, resources, from) if err != nil { return irTLSConfig, fmt.Errorf("failed to get crl from ref: %w", err) } @@ -865,11 +870,17 @@ func (t *Translator) buildListenerTLSParameters(policy *egv1a1.ClientTrafficPoli } // validateAndGetDataAtKeyInRef validates the secret object reference and gets the data at the key in the secret or configmap -func (t *Translator) validateAndGetDataAtKeyInRef(ref gwapiv1.SecretObjectReference, key string, resources *resource.Resources, from crossNamespaceFrom) ([]byte, error) { +func (t *Translator) validateAndGetDataAtKeyInRef( + translatorContext *TranslatorContext, + ref gwapiv1.SecretObjectReference, + key string, + resources *resource.Resources, + from crossNamespaceFrom, +) ([]byte, error) { refKind := string(ptr.Deref(ref.Kind, resource.KindSecret)) switch refKind { case resource.KindSecret: - secret, err := t.validateSecretRef(false, from, ref, resources) + secret, err := t.validateSecretRef(translatorContext, false, from, ref, resources) if err != nil { return nil, err } @@ -880,7 +891,7 @@ func (t *Translator) validateAndGetDataAtKeyInRef(ref gwapiv1.SecretObjectRefere } return secretCertBytes, nil case resource.KindConfigMap: - configMap, err := t.validateConfigMapRef(false, from, ref, resources) + configMap, err := t.validateConfigMapRef(translatorContext, false, from, ref, resources) if err != nil { return nil, err } @@ -891,7 +902,7 @@ func (t *Translator) validateAndGetDataAtKeyInRef(ref gwapiv1.SecretObjectRefere } return []byte(configMapData), nil case resource.KindClusterTrustBundle: - trustBundle := resources.GetClusterTrustBundle(string(ref.Name)) + trustBundle := translatorContext.GetClusterTrustBundle(string(ref.Name)) if trustBundle == nil { return nil, fmt.Errorf("ref ClusterTrustBundle [%s] not found", ref.Name) } diff --git a/internal/gatewayapi/contexts.go b/internal/gatewayapi/contexts.go index 8ee05a241de..8369eaff4ae 100644 --- a/internal/gatewayapi/contexts.go +++ b/internal/gatewayapi/contexts.go @@ -6,7 +6,9 @@ package gatewayapi import ( + certificatesv1b1 "k8s.io/api/certificates/v1beta1" corev1 "k8s.io/api/core/v1" + discoveryv1 "k8s.io/api/discovery/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" @@ -14,10 +16,12 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" gwapiv1a3 "sigs.k8s.io/gateway-api/apis/v1alpha3" + mcsapiv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/gatewayapi/resource" "github.com/envoyproxy/gateway/internal/ir" + "github.com/envoyproxy/gateway/internal/utils" ) // GatewayContext wraps a Gateway and provides helper methods for @@ -661,3 +665,163 @@ func (d DirectBackendRef) GetBackendRef() *gwapiv1.BackendRef { func (d DirectBackendRef) GetFilters() any { return nil } + +type backendServiceKey struct { + kind string + namespace string + name string +} + +type TranslatorContext struct { + NamespaceMap map[types.NamespacedName]*corev1.Namespace + ServiceMap map[types.NamespacedName]*corev1.Service + ServiceImportMap map[types.NamespacedName]*mcsapiv1a1.ServiceImport + BackendMap map[types.NamespacedName]*egv1a1.Backend + SecretMap map[types.NamespacedName]*corev1.Secret + ConfigMapMap map[types.NamespacedName]*corev1.ConfigMap + ClusterTrustBundleMap map[types.NamespacedName]*certificatesv1b1.ClusterTrustBundle + EndpointSliceMap map[backendServiceKey][]*discoveryv1.EndpointSlice +} + +func (t *TranslatorContext) GetNamespace(name string) *corev1.Namespace { + if ns, ok := t.NamespaceMap[types.NamespacedName{Name: name}]; ok { + return ns + } + return nil +} + +func (t *TranslatorContext) SetNamespaces(namespaces []*corev1.Namespace) { + namespaceMap := make(map[types.NamespacedName]*corev1.Namespace, len(namespaces)) + for _, ns := range namespaces { + namespaceMap[types.NamespacedName{Name: ns.Name}] = ns + } + t.NamespaceMap = namespaceMap +} + +func (t *TranslatorContext) GetService(namespace, name string) *corev1.Service { + if svc, ok := t.ServiceMap[types.NamespacedName{Namespace: namespace, Name: name}]; ok { + return svc + } + return nil +} + +func (t *TranslatorContext) SetServices(svcs []*corev1.Service) { + serviceMap := make(map[types.NamespacedName]*corev1.Service, len(svcs)) + for _, svc := range svcs { + serviceMap[utils.NamespacedName(svc)] = svc + } + t.ServiceMap = serviceMap +} + +func (t *TranslatorContext) GetServiceImport(namespace, name string) *mcsapiv1a1.ServiceImport { + if svcImp, ok := t.ServiceImportMap[types.NamespacedName{Namespace: namespace, Name: name}]; ok { + return svcImp + } + return nil +} + +func (t *TranslatorContext) SetServiceImports(svcImps []*mcsapiv1a1.ServiceImport) { + serviceImportMap := make(map[types.NamespacedName]*mcsapiv1a1.ServiceImport, len(svcImps)) + for _, svcImp := range svcImps { + serviceImportMap[utils.NamespacedName(svcImp)] = svcImp + } + t.ServiceImportMap = serviceImportMap +} + +func (t *TranslatorContext) GetBackend(namespace, name string) *egv1a1.Backend { + if backend, ok := t.BackendMap[types.NamespacedName{Namespace: namespace, Name: name}]; ok { + return backend + } + return nil +} + +func (t *TranslatorContext) SetBackends(backends []*egv1a1.Backend) { + backendMap := make(map[types.NamespacedName]*egv1a1.Backend, len(backends)) + for _, backend := range backends { + backendMap[utils.NamespacedName(backend)] = backend + } + t.BackendMap = backendMap +} + +func (t *TranslatorContext) GetSecret(namespace, name string) *corev1.Secret { + if secret, ok := t.SecretMap[types.NamespacedName{Namespace: namespace, Name: name}]; ok { + return secret + } + return nil +} + +func (t *TranslatorContext) SetSecrets(secrets []*corev1.Secret) { + secretMap := make(map[types.NamespacedName]*corev1.Secret, len(secrets)) + for _, secret := range secrets { + secretMap[utils.NamespacedName(secret)] = secret + } + t.SecretMap = secretMap +} + +func (t *TranslatorContext) GetConfigMap(namespace, name string) *corev1.ConfigMap { + if configMap, ok := t.ConfigMapMap[types.NamespacedName{Namespace: namespace, Name: name}]; ok { + return configMap + } + return nil +} + +func (t *TranslatorContext) SetConfigMaps(configMaps []*corev1.ConfigMap) { + configMapMap := make(map[types.NamespacedName]*corev1.ConfigMap, len(configMaps)) + for _, configMap := range configMaps { + configMapMap[utils.NamespacedName(configMap)] = configMap + } + t.ConfigMapMap = configMapMap +} + +func (t *TranslatorContext) GetClusterTrustBundle(name string) *certificatesv1b1.ClusterTrustBundle { + if ctb, ok := t.ClusterTrustBundleMap[types.NamespacedName{Name: name}]; ok { + return ctb + } + return nil +} + +func (t *TranslatorContext) SetClusterTrustBundles(ctbs []*certificatesv1b1.ClusterTrustBundle) { + ctbMap := make(map[types.NamespacedName]*certificatesv1b1.ClusterTrustBundle, len(ctbs)) + for _, ctb := range ctbs { + ctbMap[types.NamespacedName{Name: ctb.Name}] = ctb + } + t.ClusterTrustBundleMap = ctbMap +} + +func (t *TranslatorContext) GetEndpointSlicesForBackend(svcNamespace, svcName, backendKind string) []*discoveryv1.EndpointSlice { + key := backendServiceKey{ + kind: backendKind, + namespace: svcNamespace, + name: svcName, + } + if slices, ok := t.EndpointSliceMap[key]; ok { + return slices + } + return nil +} + +func (t *TranslatorContext) SetEndpointSlicesForBackend(slices []*discoveryv1.EndpointSlice) { + t.EndpointSliceMap = make(map[backendServiceKey][]*discoveryv1.EndpointSlice) + + for _, slice := range slices { + var kind string + var svcName string + + if name, ok := slice.Labels[discoveryv1.LabelServiceName]; ok { + kind = resource.KindService + svcName = name + } else if name, ok := slice.Labels[mcsapiv1a1.LabelServiceName]; ok { + kind = resource.KindServiceImport + svcName = name + } else { + continue + } + + key := backendServiceKey{ + kind: kind, + namespace: slice.Namespace, + name: svcName, + } + t.EndpointSliceMap[key] = append(t.EndpointSliceMap[key], slice) + } +} diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go index c0322b943e5..70d17fd8135 100644 --- a/internal/gatewayapi/envoyextensionpolicy.go +++ b/internal/gatewayapi/envoyextensionpolicy.go @@ -33,7 +33,8 @@ import ( // oci URL prefix const ociURLPrefix = "oci://" -func (t *Translator) ProcessEnvoyExtensionPolicies(envoyExtensionPolicies []*egv1a1.EnvoyExtensionPolicy, +func (t *Translator) ProcessEnvoyExtensionPolicies(translatorContext *TranslatorContext, + envoyExtensionPolicies []*egv1a1.EnvoyExtensionPolicy, gateways []*GatewayContext, routes []RouteContext, resources *resource.Resources, @@ -85,7 +86,7 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(envoyExtensionPolicies []*egv handledPolicies[policyName] = policy } - t.processEnvoyExtensionPolicyForRoute(resources, xdsIR, + t.processEnvoyExtensionPolicyForRoute(translatorContext, resources, xdsIR, routeMap, gatewayRouteMap, policy, currTarget) } } @@ -105,7 +106,7 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(envoyExtensionPolicies []*egv handledPolicies[policyName] = policy } - t.processEnvoyExtensionPolicyForRoute(resources, xdsIR, + t.processEnvoyExtensionPolicyForRoute(translatorContext, resources, xdsIR, routeMap, gatewayRouteMap, policy, currTarget) } } @@ -125,7 +126,7 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(envoyExtensionPolicies []*egv handledPolicies[policyName] = policy } - t.processEnvoyExtensionPolicyForGateway(resources, xdsIR, + t.processEnvoyExtensionPolicyForGateway(translatorContext, resources, xdsIR, gatewayMap, gatewayRouteMap, policy, currTarget) } } @@ -145,7 +146,7 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(envoyExtensionPolicies []*egv handledPolicies[policyName] = policy } - t.processEnvoyExtensionPolicyForGateway(resources, xdsIR, + t.processEnvoyExtensionPolicyForGateway(translatorContext, resources, xdsIR, gatewayMap, gatewayRouteMap, policy, currTarget) } } @@ -161,6 +162,7 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(envoyExtensionPolicies []*egv } func (t *Translator) processEnvoyExtensionPolicyForRoute( + translatorContext *TranslatorContext, resources *resource.Resources, xdsIR resource.XdsIRMap, routeMap map[policyTargetRouteKey]*policyRouteTargetContext, @@ -230,7 +232,7 @@ func (t *Translator) processEnvoyExtensionPolicyForRoute( } // Set conditions for translation error if it got any - if err := t.translateEnvoyExtensionPolicyForRoute(policy, targetedRoute, currTarget, xdsIR, resources); err != nil { + if err := t.translateEnvoyExtensionPolicyForRoute(translatorContext, policy, targetedRoute, currTarget, xdsIR, resources); err != nil { status.SetTranslationErrorForPolicyAncestors(&policy.Status, ancestorRefs, t.GatewayControllerName, @@ -263,6 +265,7 @@ func (t *Translator) processEnvoyExtensionPolicyForRoute( } func (t *Translator) processEnvoyExtensionPolicyForGateway( + translatorContext *TranslatorContext, resources *resource.Resources, xdsIR resource.XdsIRMap, gatewayMap map[types.NamespacedName]*policyGatewayTargetContext, @@ -301,7 +304,7 @@ func (t *Translator) processEnvoyExtensionPolicyForGateway( } // Set conditions for translation error if it got any - if err := t.translateEnvoyExtensionPolicyForGateway(policy, currTarget, targetedGateway, xdsIR, resources); err != nil { + if err := t.translateEnvoyExtensionPolicyForGateway(translatorContext, policy, currTarget, targetedGateway, xdsIR, resources); err != nil { status.SetTranslationErrorForPolicyAncestor(&policy.Status, &ancestorRef, t.GatewayControllerName, @@ -451,6 +454,7 @@ func resolveEnvoyExtensionPolicyRouteTargetRef( } func (t *Translator) translateEnvoyExtensionPolicyForRoute( + translatorContext *TranslatorContext, policy *egv1a1.EnvoyExtensionPolicy, route RouteContext, target gwapiv1.LocalPolicyTargetReferenceWithSectionName, @@ -465,7 +469,7 @@ func (t *Translator) translateEnvoyExtensionPolicyForRoute( errs error ) - if wasms, wasmError, wasmFailOpen = t.buildWasms(policy, resources); wasmError != nil { + if wasms, wasmError, wasmFailOpen = t.buildWasms(translatorContext, policy, resources); wasmError != nil { wasmError = perr.WithMessage(wasmError, "Wasm") errs = errors.Join(errs, wasmError) } @@ -481,13 +485,13 @@ func (t *Translator) translateEnvoyExtensionPolicyForRoute( continue } - if luas, luaError = t.buildLuas(policy, resources, gtwCtx.envoyProxy); luaError != nil { + if luas, luaError = t.buildLuas(translatorContext, policy, gtwCtx.envoyProxy); luaError != nil { luaError = perr.WithMessage(luaError, "Lua") errs = errors.Join(errs, luaError) } var extProcs []ir.ExtProc - if extProcs, extProcError, extProcFailOpen = t.buildExtProcs(policy, resources, gtwCtx.envoyProxy); extProcError != nil { + if extProcs, extProcError, extProcFailOpen = t.buildExtProcs(translatorContext, policy, resources, gtwCtx.envoyProxy); extProcError != nil { extProcError = perr.WithMessage(extProcError, "ExtProc") errs = errors.Join(errs, extProcError) } @@ -547,6 +551,7 @@ func (t *Translator) translateEnvoyExtensionPolicyForRoute( } func (t *Translator) translateEnvoyExtensionPolicyForGateway( + translatorContext *TranslatorContext, policy *egv1a1.EnvoyExtensionPolicy, target gwapiv1.LocalPolicyTargetReferenceWithSectionName, gateway *GatewayContext, @@ -562,15 +567,15 @@ func (t *Translator) translateEnvoyExtensionPolicyForGateway( errs error ) - if extProcs, extProcError, extProcFailOpen = t.buildExtProcs(policy, resources, gateway.envoyProxy); extProcError != nil { + if extProcs, extProcError, extProcFailOpen = t.buildExtProcs(translatorContext, policy, resources, gateway.envoyProxy); extProcError != nil { extProcError = perr.WithMessage(extProcError, "ExtProc") errs = errors.Join(errs, extProcError) } - if wasms, wasmError, wasmFailOpen = t.buildWasms(policy, resources); wasmError != nil { + if wasms, wasmError, wasmFailOpen = t.buildWasms(translatorContext, policy, resources); wasmError != nil { wasmError = perr.WithMessage(wasmError, "Wasm") errs = errors.Join(errs, wasmError) } - if luas, luaError = t.buildLuas(policy, resources, gateway.envoyProxy); luaError != nil { + if luas, luaError = t.buildLuas(translatorContext, policy, gateway.envoyProxy); luaError != nil { luaError = perr.WithMessage(luaError, "Lua") errs = errors.Join(errs, luaError) } @@ -635,7 +640,11 @@ func (t *Translator) translateEnvoyExtensionPolicyForGateway( return errs } -func (t *Translator) buildLuas(policy *egv1a1.EnvoyExtensionPolicy, resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy) ([]ir.Lua, error) { +func (t *Translator) buildLuas( + translatorContext *TranslatorContext, + policy *egv1a1.EnvoyExtensionPolicy, + envoyProxy *egv1a1.EnvoyProxy, +) ([]ir.Lua, error) { if policy == nil { return nil, nil } @@ -644,7 +653,7 @@ func (t *Translator) buildLuas(policy *egv1a1.EnvoyExtensionPolicy, resources *r for idx, ep := range policy.Spec.Lua { name := irConfigNameForLua(policy, idx) - luaIR, err := t.buildLua(name, policy, ep, resources, envoyProxy) + luaIR, err := t.buildLua(translatorContext, name, policy, ep, envoyProxy) if err != nil { return nil, err } @@ -654,16 +663,16 @@ func (t *Translator) buildLuas(policy *egv1a1.EnvoyExtensionPolicy, resources *r } func (t *Translator) buildLua( + translatorContext *TranslatorContext, name string, policy *egv1a1.EnvoyExtensionPolicy, lua egv1a1.Lua, - resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy, ) (*ir.Lua, error) { var luaCode *string var err error if lua.Type == egv1a1.LuaValueTypeValueRef { - luaCode, err = getLuaBodyFromLocalObjectReference(lua.ValueRef, resources, policy.Namespace) + luaCode, err = getLuaBodyFromLocalObjectReference(translatorContext, lua.ValueRef, policy.Namespace) } else { luaCode = lua.Inline } @@ -681,8 +690,12 @@ func (t *Translator) buildLua( } // getLuaBodyFromLocalObjectReference assumes the local object reference points to a Kubernetes ConfigMap -func getLuaBodyFromLocalObjectReference(valueRef *gwapiv1.LocalObjectReference, resources *resource.Resources, policyNs string) (*string, error) { - cm := resources.GetConfigMap(policyNs, string(valueRef.Name)) +func getLuaBodyFromLocalObjectReference( + translatorContext *TranslatorContext, + valueRef *gwapiv1.LocalObjectReference, + policyNs string, +) (*string, error) { + cm := translatorContext.GetConfigMap(policyNs, string(valueRef.Name)) if cm != nil { b, dataOk := cm.Data["lua"] switch { @@ -703,7 +716,7 @@ func getLuaBodyFromLocalObjectReference(valueRef *gwapiv1.LocalObjectReference, } } -func (t *Translator) buildExtProcs(policy *egv1a1.EnvoyExtensionPolicy, resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy) ([]ir.ExtProc, error, bool) { +func (t *Translator) buildExtProcs(translatorContext *TranslatorContext, policy *egv1a1.EnvoyExtensionPolicy, resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy) ([]ir.ExtProc, error, bool) { var ( failOpen bool errs error @@ -718,7 +731,7 @@ func (t *Translator) buildExtProcs(policy *egv1a1.EnvoyExtensionPolicy, resource hasFailClose := false for idx, ep := range policy.Spec.ExtProc { name := irConfigNameForExtProc(policy, idx) - extProcIR, err := t.buildExtProc(name, policy, ep, idx, resources, envoyProxy) + extProcIR, err := t.buildExtProc(translatorContext, name, policy, ep, idx, resources, envoyProxy) if err != nil { errs = errors.Join(errs, err) if ep.FailOpen == nil || !*ep.FailOpen { @@ -737,6 +750,7 @@ func (t *Translator) buildExtProcs(policy *egv1a1.EnvoyExtensionPolicy, resource } func (t *Translator) buildExtProc( + translatorContext *TranslatorContext, name string, policy *egv1a1.EnvoyExtensionPolicy, extProc egv1a1.ExtProc, @@ -750,7 +764,7 @@ func (t *Translator) buildExtProc( err error ) - if rd, err = t.translateExtServiceBackendRefs(policy, extProc.BackendRefs, ir.GRPC, resources, envoyProxy, "extproc", extProcIdx); err != nil { + if rd, err = t.translateExtServiceBackendRefs(translatorContext, policy, extProc.BackendRefs, ir.GRPC, resources, envoyProxy, "extproc", extProcIdx); err != nil { return nil, err } @@ -846,6 +860,7 @@ func irConfigNameForLua(policy *egv1a1.EnvoyExtensionPolicy, index int) string { } func (t *Translator) buildWasms( + translatorContext *TranslatorContext, policy *egv1a1.EnvoyExtensionPolicy, resources *resource.Resources, ) ([]ir.Wasm, error, bool) { @@ -871,7 +886,7 @@ func (t *Translator) buildWasms( hasFailClose := false for idx, wasm := range policy.Spec.Wasm { name := irConfigNameForWasm(policy, idx) - wasmIR, err := t.buildWasm(name, &wasm, policy, idx, resources) + wasmIR, err := t.buildWasm(translatorContext, name, &wasm, policy, idx, resources) if err != nil { errs = errors.Join(errs, err) if wasm.FailOpen == nil || !*wasm.FailOpen { @@ -891,6 +906,7 @@ func (t *Translator) buildWasms( } func (t *Translator) buildWasm( + translatorContext *TranslatorContext, name string, config *egv1a1.Wasm, policy *egv1a1.EnvoyExtensionPolicy, @@ -975,7 +991,7 @@ func (t *Translator) buildWasm( namespace: policy.Namespace, } - if secret, err = t.validateSecretRef( + if secret, err = t.validateSecretRef(translatorContext, false, from, *image.PullSecretRef, resources); err != nil { return nil, err } diff --git a/internal/gatewayapi/ext_service.go b/internal/gatewayapi/ext_service.go index d1f607b1e17..189209b6453 100644 --- a/internal/gatewayapi/ext_service.go +++ b/internal/gatewayapi/ext_service.go @@ -23,6 +23,7 @@ import ( // translateExtServiceBackendRefs translates external service backend references to route destinations. func (t *Translator) translateExtServiceBackendRefs( + translatorContext *TranslatorContext, policy client.Object, backendRefs []egv1a1.BackendRef, protocol ir.AppProtocol, @@ -46,6 +47,7 @@ func (t *Translator) translateExtServiceBackendRefs( destName := irIndexedExtServiceDestinationName(pnn, policy.GetObjectKind().GroupVersionKind().Kind, configType, index) for i, backendRef := range backendRefs { if err = t.validateExtServiceBackendReference( + translatorContext, &backendRef.BackendObjectReference, policy.GetNamespace(), policy.GetObjectKind().GroupVersionKind().Kind, @@ -56,6 +58,7 @@ func (t *Translator) translateExtServiceBackendRefs( settingName := irDestinationSettingName(destName, i) var extServiceDest *ir.DestinationSetting if extServiceDest, err = t.processExtServiceDestination( + translatorContext, settingName, &backendRef, pnn, @@ -87,6 +90,7 @@ func (t *Translator) translateExtServiceBackendRefs( } func (t *Translator) processExtServiceDestination( + translatorContext *TranslatorContext, settingName string, backendRef *egv1a1.BackendRef, policyNamespacedName types.NamespacedName, @@ -105,12 +109,12 @@ func (t *Translator) processExtServiceDestination( switch KindDerefOr(backendRef.Kind, resource.KindService) { case resource.KindService: - ds, err = t.processServiceDestinationSetting(settingName, backendRef.BackendObjectReference, backendNamespace, protocol, resources, envoyProxy) + ds, err = t.processServiceDestinationSetting(translatorContext, settingName, backendRef.BackendObjectReference, backendNamespace, protocol, envoyProxy) if err != nil { return nil, err } case resource.KindServiceImport: - ds, err = t.processServiceImportDestinationSetting(settingName, backendRef.BackendObjectReference, backendNamespace, protocol, resources, envoyProxy) + ds, err = t.processServiceImportDestinationSetting(translatorContext, settingName, backendRef.BackendObjectReference, backendNamespace, protocol, envoyProxy) if err != nil { return nil, err } @@ -118,7 +122,7 @@ func (t *Translator) processExtServiceDestination( if !t.BackendEnabled { return nil, fmt.Errorf("resource %s of type Backend cannot be used since Backend is disabled in Envoy Gateway configuration", string(backendRef.Name)) } - ds = t.processBackendDestinationSetting(settingName, backendRef.BackendObjectReference, backendNamespace, protocol, resources) + ds = t.processBackendDestinationSetting(translatorContext, settingName, backendRef.BackendObjectReference, backendNamespace, protocol) // Dynamic resolver destinations are not supported for none-route destinations if ds.IsDynamicResolver { return nil, errors.New("dynamic resolver destinations are not supported") @@ -137,6 +141,7 @@ func (t *Translator) processExtServiceDestination( } backendTLS, err = t.applyBackendTLSSetting( + translatorContext, backendRef.BackendObjectReference, backendNamespace, // Gateway is not the appropriate parent reference here because the owner diff --git a/internal/gatewayapi/filters.go b/internal/gatewayapi/filters.go index 545c931d746..80f0bf0a6e0 100644 --- a/internal/gatewayapi/filters.go +++ b/internal/gatewayapi/filters.go @@ -32,7 +32,7 @@ type HTTPFiltersTranslator interface { processRedirectFilter(redirect *gwapiv1.HTTPRequestRedirectFilter, filterContext *HTTPFiltersContext) processRequestHeaderModifierFilter(headerModifier *gwapiv1.HTTPHeaderFilter, filterContext *HTTPFiltersContext) processResponseHeaderModifierFilter(headerModifier *gwapiv1.HTTPHeaderFilter, filterContext *HTTPFiltersContext) - processRequestMirrorFilter(filterIdx int, mirror *gwapiv1.HTTPRequestMirrorFilter, filterContext *HTTPFiltersContext, resources *resource.Resources) status.Error + processRequestMirrorFilter(translatorContext *TranslatorContext, filterIdx int, mirror *gwapiv1.HTTPRequestMirrorFilter, filterContext *HTTPFiltersContext, resources *resource.Resources) status.Error processUnsupportedHTTPFilter(filterType string, filterContext *HTTPFiltersContext) } @@ -70,7 +70,8 @@ type HTTPFilterIR struct { var HeaderValueRegexp = regexp.MustCompile(`^[!-~]+([\t ]?[!-~]+)*$`) // ProcessHTTPFilters translates gateway api http filters to IRs. -func (t *Translator) ProcessHTTPFilters(parentRef *RouteParentContext, +func (t *Translator) ProcessHTTPFilters(translatorContext *TranslatorContext, + parentRef *RouteParentContext, route RouteContext, filters []gwapiv1.HTTPRouteFilter, ruleIdx int, @@ -104,11 +105,11 @@ func (t *Translator) ProcessHTTPFilters(parentRef *RouteParentContext, case gwapiv1.HTTPRouteFilterResponseHeaderModifier: t.processResponseHeaderModifierFilter(filter.ResponseHeaderModifier, httpFiltersContext) case gwapiv1.HTTPRouteFilterRequestMirror: - err = t.processRequestMirrorFilter(i, filter.RequestMirror, httpFiltersContext, resources) + err = t.processRequestMirrorFilter(translatorContext, i, filter.RequestMirror, httpFiltersContext, resources) case gwapiv1.HTTPRouteFilterCORS: t.processCORSFilter(filter.CORS, httpFiltersContext) case gwapiv1.HTTPRouteFilterExtensionRef: - t.processExtensionRefHTTPFilter(filter.ExtensionRef, httpFiltersContext, resources) + t.processExtensionRefHTTPFilter(translatorContext, filter.ExtensionRef, httpFiltersContext, resources) default: t.processUnsupportedHTTPFilter(string(filter.Type), httpFiltersContext) } @@ -118,7 +119,8 @@ func (t *Translator) ProcessHTTPFilters(parentRef *RouteParentContext, } // ProcessGRPCFilters translates gateway api grpc filters to IRs. -func (t *Translator) ProcessGRPCFilters(parentRef *RouteParentContext, +func (t *Translator) ProcessGRPCFilters(translatorContext *TranslatorContext, + parentRef *RouteParentContext, route RouteContext, filters []gwapiv1.GRPCRouteFilter, resources *resource.Resources, @@ -147,12 +149,12 @@ func (t *Translator) ProcessGRPCFilters(parentRef *RouteParentContext, case gwapiv1.GRPCRouteFilterResponseHeaderModifier: t.processResponseHeaderModifierFilter(filter.ResponseHeaderModifier, httpFiltersContext) case gwapiv1.GRPCRouteFilterRequestMirror: - err := t.processRequestMirrorFilter(i, filter.RequestMirror, httpFiltersContext, resources) + err := t.processRequestMirrorFilter(translatorContext, i, filter.RequestMirror, httpFiltersContext, resources) if err != nil { return nil, err } case gwapiv1.GRPCRouteFilterExtensionRef: - t.processExtensionRefHTTPFilter(filter.ExtensionRef, httpFiltersContext, resources) + t.processExtensionRefHTTPFilter(translatorContext, filter.ExtensionRef, httpFiltersContext, resources) default: t.processUnsupportedHTTPFilter(string(filter.Type), httpFiltersContext) } @@ -740,7 +742,12 @@ func (t *Translator) processResponseHeaderModifierFilter( } } -func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjectReference, filterContext *HTTPFiltersContext, resources *resource.Resources) { +func (t *Translator) processExtensionRefHTTPFilter( + translatorContext *TranslatorContext, + extFilter *gwapiv1.LocalObjectReference, + filterContext *HTTPFiltersContext, + resources *resource.Resources, +) { // Make sure the config actually exists. if extFilter == nil { return @@ -839,7 +846,7 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec dr := &ir.CustomResponse{} if hrf.Spec.DirectResponse.Body != nil { var err error - if dr.Body, err = getCustomResponseBody(hrf.Spec.DirectResponse.Body, resources, filterNs); err != nil { + if dr.Body, err = getCustomResponseBody(translatorContext, hrf.Spec.DirectResponse.Body, filterNs); err != nil { t.processInvalidHTTPFilter(string(extFilter.Kind), filterContext, err) return } @@ -883,6 +890,7 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec if hrf.Spec.CredentialInjection != nil { secret, err := t.validateSecretRef( + translatorContext, false, crossNamespaceFrom{ group: egv1a1.GroupName, @@ -954,6 +962,7 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec } func (t *Translator) processRequestMirrorFilter( + translatorContext *TranslatorContext, filterIdx int, mirrorFilter *gwapiv1.HTTPRequestMirrorFilter, filterContext *HTTPFiltersContext, @@ -980,7 +989,7 @@ func (t *Translator) processRequestMirrorFilter( // This sets the status on the Route, should the usage be changed so that the status message reflects that the backendRef is from the filter? filterNs := filterContext.Route.GetNamespace() serviceNamespace := NamespaceDerefOr(mirrorBackend.Namespace, filterNs) - err = t.validateBackendRef(mirrorBackendRef, filterContext.Route, + err = t.validateBackendRef(translatorContext, mirrorBackendRef, filterContext.Route, resources, serviceNamespace, routeType) if err != nil { return status.NewRouteStatusError( @@ -989,7 +998,7 @@ func (t *Translator) processRequestMirrorFilter( destName := fmt.Sprintf("%s-mirror-%d", irRouteDestinationName(filterContext.Route, filterContext.RuleIdx), filterIdx) settingName := irDestinationSettingName(destName, -1 /*unused*/) - ds, _, err := t.processDestination(settingName, mirrorBackendRef, filterContext.ParentRef, filterContext.Route, resources) + ds, _, err := t.processDestination(translatorContext, settingName, mirrorBackendRef, filterContext.ParentRef, filterContext.Route, resources) if err != nil { return err } diff --git a/internal/gatewayapi/globalresources.go b/internal/gatewayapi/globalresources.go index 2aff4718f8e..f2024efcbee 100644 --- a/internal/gatewayapi/globalresources.go +++ b/internal/gatewayapi/globalresources.go @@ -19,11 +19,11 @@ import ( const envoyTLSSecretName = "envoy" // ProcessGlobalResources processes global resources that are not tied to a specific listener or route -func (t *Translator) ProcessGlobalResources(resources *resource.Resources, xdsIRs resource.XdsIRMap, gateways []*GatewayContext) error { +func (t *Translator) ProcessGlobalResources(translatorContext *TranslatorContext, resources *resource.Resources, xdsIRs resource.XdsIRMap, gateways []*GatewayContext) error { // Add the ProxyServiceCluster information for each gateway to the IR map for _, gateway := range gateways { // Get the gateway IR key and RouteDestination representing the ProxyServiceCluster - irKey, rDest := t.processServiceClusterForGateway(gateway, resources) + irKey, rDest := t.processServiceClusterForGateway(translatorContext, gateway, resources) if xdsIRs[irKey] == nil { continue @@ -41,7 +41,7 @@ func (t *Translator) ProcessGlobalResources(resources *resource.Resources, xdsIR // Get the envoy client TLS secret. It is used for envoy to establish a TLS connection with control plane components, // including the rate limit server and the wasm HTTP server. - envoyTLSSecret := resources.GetSecret(t.ControllerNamespace, envoyTLSSecretName) + envoyTLSSecret := translatorContext.GetSecret(t.ControllerNamespace, envoyTLSSecretName) if envoyTLSSecret == nil { return fmt.Errorf("envoy TLS secret %s/%s not found", t.ControllerNamespace, envoyTLSSecretName) } @@ -63,7 +63,7 @@ func (t *Translator) ProcessGlobalResources(resources *resource.Resources, xdsIR } // processServiceClusterForGateway returns the matching IR key for a gateway and builds a RouteDestination to represent the ProxyServiceCluster -func (t *Translator) processServiceClusterForGateway(gateway *GatewayContext, resources *resource.Resources) (string, *ir.RouteDestination) { +func (t *Translator) processServiceClusterForGateway(translatorContext *TranslatorContext, gateway *GatewayContext, resources *resource.Resources) (string, *ir.RouteDestination) { irKey := t.getIRKey(gateway.Gateway) labels := OwnerLabels(gateway.Gateway, t.MergeGateways) @@ -85,7 +85,7 @@ func (t *Translator) processServiceClusterForGateway(gateway *GatewayContext, re Namespace: NamespacePtr(svcCluster.Namespace), Port: PortNumPtr(svcCluster.Spec.Ports[0].Port), } - dst, err := t.processServiceDestinationSetting(irKey, bRef, svcCluster.Namespace, ir.AppProtocol(svcCluster.Spec.Ports[0].Protocol), resources, resources.EnvoyProxyForGatewayClass) + dst, err := t.processServiceDestinationSetting(translatorContext, irKey, bRef, svcCluster.Namespace, ir.AppProtocol(svcCluster.Spec.Ports[0].Protocol), resources.EnvoyProxyForGatewayClass) if err != nil { return "", nil } diff --git a/internal/gatewayapi/listener.go b/internal/gatewayapi/listener.go index 75ef2aab92a..117c067556c 100644 --- a/internal/gatewayapi/listener.go +++ b/internal/gatewayapi/listener.go @@ -32,10 +32,10 @@ import ( var _ ListenersTranslator = (*Translator)(nil) type ListenersTranslator interface { - ProcessListeners(gateways []*GatewayContext, xdsIR resource.XdsIRMap, infraIR resource.InfraIRMap, resources *resource.Resources) + ProcessListeners(translatorContext *TranslatorContext, gateways []*GatewayContext, xdsIR resource.XdsIRMap, infraIR resource.InfraIRMap, resources *resource.Resources) } -func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR resource.XdsIRMap, infraIR resource.InfraIRMap, resources *resource.Resources) { +func (t *Translator) ProcessListeners(translatorContext *TranslatorContext, gateways []*GatewayContext, xdsIR resource.XdsIRMap, infraIR resource.InfraIRMap, resources *resource.Resources) { // Infra IR proxy ports must be unique. foundPorts := make(map[string][]*protocolPort) t.validateConflictedLayer7Listeners(gateways) @@ -55,7 +55,7 @@ func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR resource infraIR[irKey].Proxy.Config = gateway.envoyProxy } t.processProxyReadyListener(xdsIR[irKey], gateway.envoyProxy) - t.processProxyObservability(gateway, xdsIR[irKey], infraIR[irKey].Proxy.Config, resources) + t.processProxyObservability(translatorContext, gateway, xdsIR[irKey], infraIR[irKey].Proxy.Config, resources) for _, listener := range gateway.listeners { // Process protocol & supported kinds @@ -95,7 +95,7 @@ func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR resource t.validateAllowedNamespaces(listener) // Process TLS configuration - t.validateTLSConfiguration(listener, resources) + t.validateTLSConfiguration(translatorContext, listener, resources) // Process Hostname configuration t.validateHostName(listener) @@ -468,24 +468,24 @@ func (t *Translator) processProxyReadyListener(xdsIR *ir.Xds, envoyProxy *egv1a1 } } -func (t *Translator) processProxyObservability(gwCtx *GatewayContext, xdsIR *ir.Xds, envoyProxy *egv1a1.EnvoyProxy, resources *resource.Resources) { +func (t *Translator) processProxyObservability(translatorContext *TranslatorContext, gwCtx *GatewayContext, xdsIR *ir.Xds, envoyProxy *egv1a1.EnvoyProxy, resources *resource.Resources) { var err error - xdsIR.AccessLog, err = t.processAccessLog(envoyProxy, resources) + xdsIR.AccessLog, err = t.processAccessLog(translatorContext, envoyProxy, resources) if err != nil { status.UpdateGatewayStatusNotAccepted(gwCtx.Gateway, gwapiv1.GatewayReasonInvalidParameters, fmt.Sprintf("Invalid access log backendRefs in the referenced EnvoyProxy: %v", err)) return } - xdsIR.Tracing, err = t.processTracing(gwCtx.Gateway, envoyProxy, t.MergeGateways, resources) + xdsIR.Tracing, err = t.processTracing(translatorContext, gwCtx.Gateway, envoyProxy, t.MergeGateways, resources) if err != nil { status.UpdateGatewayStatusNotAccepted(gwCtx.Gateway, gwapiv1.GatewayReasonInvalidParameters, fmt.Sprintf("Invalid tracing backendRefs in the referenced EnvoyProxy: %v", err)) return } - xdsIR.Metrics, err = t.processMetrics(envoyProxy, resources) + xdsIR.Metrics, err = t.processMetrics(translatorContext, envoyProxy, resources) if err != nil { status.UpdateGatewayStatusNotAccepted(gwCtx.Gateway, gwapiv1.GatewayReasonInvalidParameters, fmt.Sprintf("Invalid metrics backendRefs in the referenced EnvoyProxy: %v", err)) @@ -523,7 +523,7 @@ func (t *Translator) processInfraIRListener(listener *ListenerContext, infraIR r infraIR[irKey].Proxy.Listeners = append(infraIR[irKey].Proxy.Listeners, proxyListener) } -func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources *resource.Resources) (*ir.AccessLog, error) { +func (t *Translator) processAccessLog(translatorContext *TranslatorContext, envoyproxy *egv1a1.EnvoyProxy, resources *resource.Resources) (*ir.AccessLog, error) { if envoyproxy == nil || envoyproxy.Spec.Telemetry == nil || envoyproxy.Spec.Telemetry.AccessLog == nil || @@ -630,7 +630,7 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources * destName := fmt.Sprintf("accesslog_als_%d_%d", i, j) settingName := irDestinationSettingName(destName, -1) // TODO: how to get authority from the backendRefs? - ds, traffic, err := t.processBackendRefs(settingName, sink.ALS.BackendCluster, envoyproxy.Namespace, resources, envoyproxy) + ds, traffic, err := t.processBackendRefs(translatorContext, settingName, sink.ALS.BackendCluster, envoyproxy.Namespace, resources, envoyproxy) if err != nil { return nil, err } @@ -677,7 +677,7 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources * destName := fmt.Sprintf("accesslog_otel_%d_%d", i, j) settingName := irDestinationSettingName(destName, -1) // TODO: how to get authority from the backendRefs? - ds, traffic, err := t.processBackendRefs(settingName, sink.OpenTelemetry.BackendCluster, envoyproxy.Namespace, resources, envoyproxy) + ds, traffic, err := t.processBackendRefs(translatorContext, settingName, sink.OpenTelemetry.BackendCluster, envoyproxy.Namespace, resources, envoyproxy) if err != nil { return nil, err } @@ -719,7 +719,7 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources * return irAccessLog, nil } -func (t *Translator) processTracing(gw *gwapiv1.Gateway, envoyproxy *egv1a1.EnvoyProxy, +func (t *Translator) processTracing(translatorContext *TranslatorContext, gw *gwapiv1.Gateway, envoyproxy *egv1a1.EnvoyProxy, mergeGateways bool, resources *resource.Resources, ) (*ir.Tracing, error) { if envoyproxy == nil || @@ -733,7 +733,7 @@ func (t *Translator) processTracing(gw *gwapiv1.Gateway, envoyproxy *egv1a1.Envo destName := "tracing" settingName := irDestinationSettingName(destName, -1) // TODO: how to get authority from the backendRefs? - ds, traffic, err := t.processBackendRefs(settingName, tracing.Provider.BackendCluster, envoyproxy.Namespace, resources, envoyproxy) + ds, traffic, err := t.processBackendRefs(translatorContext, settingName, tracing.Provider.BackendCluster, envoyproxy.Namespace, resources, envoyproxy) if err != nil { return nil, err } @@ -796,7 +796,7 @@ func proxySamplingRate(tracing *egv1a1.ProxyTracing) float64 { return rate } -func (t *Translator) processMetrics(envoyproxy *egv1a1.EnvoyProxy, resources *resource.Resources) (*ir.Metrics, error) { +func (t *Translator) processMetrics(translatorContext *TranslatorContext, envoyproxy *egv1a1.EnvoyProxy, resources *resource.Resources) (*ir.Metrics, error) { if envoyproxy == nil || envoyproxy.Spec.Telemetry == nil || envoyproxy.Spec.Telemetry.Metrics == nil { @@ -808,7 +808,7 @@ func (t *Translator) processMetrics(envoyproxy *egv1a1.EnvoyProxy, resources *re continue } - _, _, err := t.processBackendRefs("", sink.OpenTelemetry.BackendCluster, envoyproxy.Namespace, resources, envoyproxy) + _, _, err := t.processBackendRefs(translatorContext, "", sink.OpenTelemetry.BackendCluster, envoyproxy.Namespace, resources, envoyproxy) if err != nil { return nil, err } @@ -821,7 +821,7 @@ func (t *Translator) processMetrics(envoyproxy *egv1a1.EnvoyProxy, resources *re }, nil } -func (t *Translator) processBackendRefs(name string, backendCluster egv1a1.BackendCluster, namespace string, +func (t *Translator) processBackendRefs(translatorContext *TranslatorContext, name string, backendCluster egv1a1.BackendCluster, namespace string, resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy, ) ([]*ir.DestinationSetting, *ir.TrafficFeatures, error) { traffic, err := translateTrafficFeatures(backendCluster.BackendSettings) @@ -835,19 +835,19 @@ func (t *Translator) processBackendRefs(name string, backendCluster egv1a1.Backe kind := KindDerefOr(ref.Kind, resource.KindService) switch kind { case resource.KindService: - if err := validateBackendRefService(ref.BackendObjectReference, resources, ns, corev1.ProtocolTCP); err != nil { + if err := validateBackendRefService(translatorContext, ref.BackendObjectReference, ns, corev1.ProtocolTCP); err != nil { return nil, nil, err } - ds, err := t.processServiceDestinationSetting(name, ref.BackendObjectReference, ns, ir.TCP, resources, envoyProxy) + ds, err := t.processServiceDestinationSetting(translatorContext, name, ref.BackendObjectReference, ns, ir.TCP, envoyProxy) if err != nil { return nil, nil, err } result = append(result, ds) case resource.KindBackend: - if err := t.validateBackendRefBackend(ref.BackendObjectReference, resources, ns, true); err != nil { + if err := t.validateBackendRefBackend(translatorContext, ref.BackendObjectReference, resources, ns, true); err != nil { return nil, nil, err } - ds := t.processBackendDestinationSetting(name, ref.BackendObjectReference, ns, ir.TCP, resources) + ds := t.processBackendDestinationSetting(translatorContext, name, ref.BackendObjectReference, ns, ir.TCP) // Dynamic resolver destinations are not supported for none-route destinations if ds.IsDynamicResolver { return nil, nil, errors.New("dynamic resolver destinations are not supported") diff --git a/internal/gatewayapi/listener_test.go b/internal/gatewayapi/listener_test.go index e0533178c90..1f7de6bb9d0 100644 --- a/internal/gatewayapi/listener_test.go +++ b/internal/gatewayapi/listener_test.go @@ -846,6 +846,7 @@ func TestProcessTracingServiceName(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { translator := &Translator{} + translatorContext := &TranslatorContext{} resources := &resource.Resources{} // Mock service to resolve BackendRefs @@ -895,8 +896,10 @@ func TestProcessTracingServiceName(t *testing.T) { }, }, ) + translatorContext.SetServices(resources.Services) + translatorContext.SetEndpointSlicesForBackend(resources.EndpointSlices) - result, err := translator.processTracing(tc.gateway, tc.envoyProxy, tc.mergeGateways, resources) + result, err := translator.processTracing(translatorContext, tc.gateway, tc.envoyProxy, tc.mergeGateways, resources) if tc.expectError { assert.Error(t, err) diff --git a/internal/gatewayapi/resource/resource.go b/internal/gatewayapi/resource/resource.go index f06fbfe2915..49291c883b8 100644 --- a/internal/gatewayapi/resource/resource.go +++ b/internal/gatewayapi/resource/resource.go @@ -93,16 +93,6 @@ func NewResources() *Resources { } } -func (r *Resources) GetNamespace(name string) *corev1.Namespace { - for _, ns := range r.Namespaces { - if ns.Name == name { - return ns - } - } - - return nil -} - func (r *Resources) GetEnvoyProxy(namespace, name string) *egv1a1.EnvoyProxy { for _, ep := range r.EnvoyProxiesForGateways { if ep.Namespace == namespace && ep.Name == name { @@ -113,16 +103,6 @@ func (r *Resources) GetEnvoyProxy(namespace, name string) *egv1a1.EnvoyProxy { return nil } -// GetService returns the Service with the given namespace and name. -func (r *Resources) GetService(namespace, name string) *corev1.Service { - for _, svc := range r.Services { - if svc.Namespace == namespace && svc.Name == name { - return svc - } - } - return nil -} - // GetServiceByLabels returns the Service matching the given labels and namespace target. func (r *Resources) GetServiceByLabels(labels map[string]string, namespace string) *corev1.Service { for _, svc := range r.Services { @@ -137,56 +117,9 @@ func (r *Resources) GetServiceByLabels(labels map[string]string, namespace strin return nil } -func (r *Resources) GetServiceImport(namespace, name string) *mcsapiv1a1.ServiceImport { - for _, svcImp := range r.ServiceImports { - if svcImp.Namespace == namespace && svcImp.Name == name { - return svcImp - } - } - - return nil -} - -func (r *Resources) GetBackend(namespace, name string) *egv1a1.Backend { - for _, be := range r.Backends { - if be.Namespace == namespace && be.Name == name { - return be - } - } - - return nil -} - -func (r *Resources) GetSecret(namespace, name string) *corev1.Secret { - for _, secret := range r.Secrets { - if secret.Namespace == namespace && secret.Name == name { - return secret - } - } - - return nil -} - -func (r *Resources) GetClusterTrustBundle(name string) *certificatesv1b1.ClusterTrustBundle { - for _, ctb := range r.ClusterTrustBundles { - if ctb.Name == name { - return ctb - } - } - - return nil -} - -func (r *Resources) GetConfigMap(namespace, name string) *corev1.ConfigMap { - for _, configMap := range r.ConfigMaps { - if configMap.Namespace == namespace && configMap.Name == name { - return configMap - } - } - - return nil -} - +// TODO: +// this method is only used in testfile. +// SHOULD be removed after refactoring the gatewayapi package structure to resolve the cyclic import issue. func (r *Resources) GetEndpointSlicesForBackend(svcNamespace, svcName, backendKind string) []*discoveryv1.EndpointSlice { var endpointSlices []*discoveryv1.EndpointSlice for _, endpointSlice := range r.EndpointSlices { diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index a8a20d4ed72..96ea00dc999 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -47,14 +47,14 @@ var ( ) type RoutesTranslator interface { - ProcessHTTPRoutes(httpRoutes []*gwapiv1.HTTPRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*HTTPRouteContext - ProcessGRPCRoutes(grpcRoutes []*gwapiv1.GRPCRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*GRPCRouteContext - ProcessTLSRoutes(tlsRoutes []*gwapiv1a3.TLSRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*TLSRouteContext - ProcessTCPRoutes(tcpRoutes []*gwapiv1a2.TCPRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*TCPRouteContext - ProcessUDPRoutes(udpRoutes []*gwapiv1a2.UDPRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*UDPRouteContext + ProcessHTTPRoutes(translatorContext *TranslatorContext, httpRoutes []*gwapiv1.HTTPRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*HTTPRouteContext + ProcessGRPCRoutes(translatorContext *TranslatorContext, grpcRoutes []*gwapiv1.GRPCRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*GRPCRouteContext + ProcessTLSRoutes(translatorContext *TranslatorContext, tlsRoutes []*gwapiv1a3.TLSRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*TLSRouteContext + ProcessTCPRoutes(translatorContext *TranslatorContext, tcpRoutes []*gwapiv1a2.TCPRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*TCPRouteContext + ProcessUDPRoutes(translatorContext *TranslatorContext, udpRoutes []*gwapiv1a2.UDPRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*UDPRouteContext } -func (t *Translator) ProcessHTTPRoutes(httpRoutes []*gwapiv1.HTTPRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*HTTPRouteContext { +func (t *Translator) ProcessHTTPRoutes(translatorContext *TranslatorContext, httpRoutes []*gwapiv1.HTTPRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*HTTPRouteContext { relevantHTTPRoutes := make([]*HTTPRouteContext, 0, len(httpRoutes)) // HTTPRoutes are already sorted by the provider layer @@ -68,20 +68,20 @@ func (t *Translator) ProcessHTTPRoutes(httpRoutes []*gwapiv1.HTTPRoute, gateways // Find out if this route attaches to one of our Gateway's listeners, // and if so, get the list of listeners that allow it to attach for each // parentRef. - relevantRoute := t.processAllowedListenersForParentRefs(httpRoute, gateways, resources) + relevantRoute := t.processAllowedListenersForParentRefs(translatorContext, httpRoute, gateways) if !relevantRoute { continue } relevantHTTPRoutes = append(relevantHTTPRoutes, httpRoute) - t.processHTTPRouteParentRefs(httpRoute, resources, xdsIR) + t.processHTTPRouteParentRefs(translatorContext, httpRoute, resources, xdsIR) } return relevantHTTPRoutes } -func (t *Translator) ProcessGRPCRoutes(grpcRoutes []*gwapiv1.GRPCRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*GRPCRouteContext { +func (t *Translator) ProcessGRPCRoutes(translatorContext *TranslatorContext, grpcRoutes []*gwapiv1.GRPCRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*GRPCRouteContext { relevantGRPCRoutes := make([]*GRPCRouteContext, 0, len(grpcRoutes)) // GRPCRoutes are already sorted by the provider layer @@ -95,25 +95,25 @@ func (t *Translator) ProcessGRPCRoutes(grpcRoutes []*gwapiv1.GRPCRoute, gateways // Find out if this route attaches to one of our Gateway's listeners, // and if so, get the list of listeners that allow it to attach for each // parentRef. - relevantRoute := t.processAllowedListenersForParentRefs(grpcRoute, gateways, resources) + relevantRoute := t.processAllowedListenersForParentRefs(translatorContext, grpcRoute, gateways) if !relevantRoute { continue } relevantGRPCRoutes = append(relevantGRPCRoutes, grpcRoute) - t.processGRPCRouteParentRefs(grpcRoute, resources, xdsIR) + t.processGRPCRouteParentRefs(translatorContext, grpcRoute, resources, xdsIR) } return relevantGRPCRoutes } -func (t *Translator) processHTTPRouteParentRefs(httpRoute *HTTPRouteContext, resources *resource.Resources, xdsIR resource.XdsIRMap) { +func (t *Translator) processHTTPRouteParentRefs(translatorContext *TranslatorContext, httpRoute *HTTPRouteContext, resources *resource.Resources, xdsIR resource.XdsIRMap) { for _, parentRef := range httpRoute.ParentRefs { // Need to compute Route rules within the parentRef loop because // any conditions that come out of it have to go on each RouteParentStatus, // not on the Route as a whole. - routeRoutes, errs := t.processHTTPRouteRules(httpRoute, parentRef, resources) + routeRoutes, errs := t.processHTTPRouteRules(translatorContext, httpRoute, parentRef, resources) // TODO: zhaohuabing: according to the gateway api, the RouteConditionPartiallyInvalid condition should be set // to true when an HTTPRoute contains a combination of both valid and invalid rules. if len(errs) > 0 { @@ -178,7 +178,7 @@ func (t *Translator) processHTTPRouteParentRefs(httpRoute *HTTPRouteContext, res } } -func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRef *RouteParentContext, resources *resource.Resources) ([]*ir.HTTPRoute, []status.Error) { +func (t *Translator) processHTTPRouteRules(translatorContext *TranslatorContext, httpRoute *HTTPRouteContext, parentRef *RouteParentContext, resources *resource.Resources) ([]*ir.HTTPRoute, []status.Error) { var ( irRoutes []*ir.HTTPRoute errorCollector = &status.TypedErrorCollector{} @@ -188,7 +188,7 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe // process each HTTPRouteRule, generate a unique Xds IR HTTPRoute per match of the rule for ruleIdx, rule := range httpRoute.Spec.Rules { // process HTTP Route filters first, so that the filters can be applied to the IR route later - httpFiltersContext, err := t.ProcessHTTPFilters(parentRef, httpRoute, rule.Filters, ruleIdx, resources) + httpFiltersContext, err := t.ProcessHTTPFilters(translatorContext, parentRef, httpRoute, rule.Filters, ruleIdx, resources) if err != nil { // Some errors should be treated as ResolvedRefs condition type, // e.g. Failed to resolve the BackendRef in the RequestMirror filter. @@ -234,7 +234,7 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe Filters: rule.BackendRefs[i].Filters, } // ds will never be nil here because processDestination returns an empty DestinationSetting for invalid backendRefs. - ds, unstructuredRef, err := t.processDestination(settingName, backendRefCtx, parentRef, httpRoute, resources) + ds, unstructuredRef, err := t.processDestination(translatorContext, settingName, backendRefCtx, parentRef, httpRoute, resources) if err != nil { // Gateway API conformance: When backendRef Service exists but has no endpoints, // the ResolvedRefs condition should NOT be set to False. @@ -708,13 +708,13 @@ func applyHTTPFiltersContextToIRRoute(httpFiltersContext *HTTPFiltersContext, ir } } -func (t *Translator) processGRPCRouteParentRefs(grpcRoute *GRPCRouteContext, resources *resource.Resources, xdsIR resource.XdsIRMap) { +func (t *Translator) processGRPCRouteParentRefs(translatorContext *TranslatorContext, grpcRoute *GRPCRouteContext, resources *resource.Resources, xdsIR resource.XdsIRMap) { for _, parentRef := range grpcRoute.ParentRefs { // Need to compute Route rules within the parentRef loop because // any conditions that come out of it have to go on each RouteParentStatus, // not on the Route as a whole. - routeRoutes, errs := t.processGRPCRouteRules(grpcRoute, parentRef, resources) + routeRoutes, errs := t.processGRPCRouteRules(translatorContext, grpcRoute, parentRef, resources) if len(errs) > 0 { routeStatus := GetRouteStatus(grpcRoute) for _, err := range errs { @@ -775,7 +775,7 @@ func (t *Translator) processGRPCRouteParentRefs(grpcRoute *GRPCRouteContext, res } } -func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRef *RouteParentContext, resources *resource.Resources) ([]*ir.HTTPRoute, []status.Error) { +func (t *Translator) processGRPCRouteRules(translatorContext *TranslatorContext, grpcRoute *GRPCRouteContext, parentRef *RouteParentContext, resources *resource.Resources) ([]*ir.HTTPRoute, []status.Error) { var ( irRoutes []*ir.HTTPRoute errorCollector = &status.TypedErrorCollector{} @@ -787,7 +787,7 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe rule := &grpcRoute.Spec.Rules[ruleIdx] // process GRPC route filters first, so that the filters can be applied to the IR route later - httpFiltersContext, err := t.ProcessGRPCFilters(parentRef, grpcRoute, rule.Filters, resources) + httpFiltersContext, err := t.ProcessGRPCFilters(translatorContext, parentRef, grpcRoute, rule.Filters, resources) if err != nil { errorCollector.Add(status.NewRouteStatusError( fmt.Errorf("failed to process route rule %d: %w", ruleIdx, err), @@ -823,7 +823,7 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe Filters: rule.BackendRefs[i].Filters, } // ds will never be nil here because processDestination returns an empty DestinationSetting for invalid backendRefs. - ds, _, err := t.processDestination(settingName, backendRefCtx, parentRef, grpcRoute, resources) + ds, _, err := t.processDestination(translatorContext, settingName, backendRefCtx, parentRef, grpcRoute, resources) if err != nil { // Gateway API conformance: When backendRef Service exists but has no endpoints, // the ResolvedRefs condition should NOT be set to False. @@ -1145,7 +1145,7 @@ func filterEGPrefix(in map[string]string) map[string]string { return out } -func (t *Translator) ProcessTLSRoutes(tlsRoutes []*gwapiv1a3.TLSRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*TLSRouteContext { +func (t *Translator) ProcessTLSRoutes(translatorContext *TranslatorContext, tlsRoutes []*gwapiv1a3.TLSRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap) []*TLSRouteContext { relevantTLSRoutes := make([]*TLSRouteContext, 0, len(tlsRoutes)) // TLSRoutes are already sorted by the provider layer @@ -1158,20 +1158,20 @@ func (t *Translator) ProcessTLSRoutes(tlsRoutes []*gwapiv1a3.TLSRoute, gateways // Find out if this route attaches to one of our Gateway's listeners, // and if so, get the list of listeners that allow it to attach for each // parentRef. - relevantRoute := t.processAllowedListenersForParentRefs(tlsRoute, gateways, resources) + relevantRoute := t.processAllowedListenersForParentRefs(translatorContext, tlsRoute, gateways) if !relevantRoute { continue } relevantTLSRoutes = append(relevantTLSRoutes, tlsRoute) - t.processTLSRouteParentRefs(tlsRoute, resources, xdsIR) + t.processTLSRouteParentRefs(translatorContext, tlsRoute, resources, xdsIR) } return relevantTLSRoutes } -func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resources *resource.Resources, xdsIR resource.XdsIRMap) { +func (t *Translator) processTLSRouteParentRefs(translatorContext *TranslatorContext, tlsRoute *TLSRouteContext, resources *resource.Resources, xdsIR resource.XdsIRMap) { for _, parentRef := range tlsRoute.ParentRefs { // Need to compute Route rules within the parentRef loop because @@ -1189,7 +1189,7 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour settingName := irDestinationSettingName(destName, i) backendRefCtx := DirectBackendRef{BackendRef: &rule.BackendRefs[i]} // ds will never be nil here because processDestination returns an empty DestinationSetting for invalid backendRefs. - ds, _, err := t.processDestination(settingName, backendRefCtx, parentRef, tlsRoute, resources) + ds, _, err := t.processDestination(translatorContext, settingName, backendRefCtx, parentRef, tlsRoute, resources) if err != nil { resolveErrs.Add(err) continue @@ -1290,7 +1290,7 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour } } -func (t *Translator) ProcessUDPRoutes(udpRoutes []*gwapiv1a2.UDPRoute, gateways []*GatewayContext, resources *resource.Resources, +func (t *Translator) ProcessUDPRoutes(translatorContext *TranslatorContext, udpRoutes []*gwapiv1a2.UDPRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap, ) []*UDPRouteContext { relevantUDPRoutes := make([]*UDPRouteContext, 0, len(udpRoutes)) @@ -1305,20 +1305,20 @@ func (t *Translator) ProcessUDPRoutes(udpRoutes []*gwapiv1a2.UDPRoute, gateways // Find out if this route attaches to one of our Gateway's listeners, // and if so, get the list of listeners that allow it to attach for each // parentRef. - relevantRoute := t.processAllowedListenersForParentRefs(udpRoute, gateways, resources) + relevantRoute := t.processAllowedListenersForParentRefs(translatorContext, udpRoute, gateways) if !relevantRoute { continue } relevantUDPRoutes = append(relevantUDPRoutes, udpRoute) - t.processUDPRouteParentRefs(udpRoute, resources, xdsIR) + t.processUDPRouteParentRefs(translatorContext, udpRoute, resources, xdsIR) } return relevantUDPRoutes } -func (t *Translator) processUDPRouteParentRefs(udpRoute *UDPRouteContext, resources *resource.Resources, xdsIR resource.XdsIRMap) { +func (t *Translator) processUDPRouteParentRefs(translatorContext *TranslatorContext, udpRoute *UDPRouteContext, resources *resource.Resources, xdsIR resource.XdsIRMap) { for _, parentRef := range udpRoute.ParentRefs { // compute backends if len(udpRoute.Spec.Rules) != 1 { @@ -1347,7 +1347,7 @@ func (t *Translator) processUDPRouteParentRefs(udpRoute *UDPRouteContext, resour settingName := irDestinationSettingName(destName, i) backendRefCtx := DirectBackendRef{BackendRef: &udpRoute.Spec.Rules[0].BackendRefs[i]} // ds will never be nil here because processDestination returns an empty DestinationSetting for invalid backendRefs. - ds, _, err := t.processDestination(settingName, backendRefCtx, parentRef, udpRoute, resources) + ds, _, err := t.processDestination(translatorContext, settingName, backendRefCtx, parentRef, udpRoute, resources) if err != nil { resolveErrs.Add(err) continue @@ -1441,7 +1441,7 @@ func (t *Translator) processUDPRouteParentRefs(udpRoute *UDPRouteContext, resour } } -func (t *Translator) ProcessTCPRoutes(tcpRoutes []*gwapiv1a2.TCPRoute, gateways []*GatewayContext, resources *resource.Resources, +func (t *Translator) ProcessTCPRoutes(translatorContext *TranslatorContext, tcpRoutes []*gwapiv1a2.TCPRoute, gateways []*GatewayContext, resources *resource.Resources, xdsIR resource.XdsIRMap, ) []*TCPRouteContext { relevantTCPRoutes := make([]*TCPRouteContext, 0, len(tcpRoutes)) @@ -1456,20 +1456,20 @@ func (t *Translator) ProcessTCPRoutes(tcpRoutes []*gwapiv1a2.TCPRoute, gateways // Find out if this route attaches to one of our Gateway's listeners, // and if so, get the list of listeners that allow it to attach for each // parentRef. - relevantRoute := t.processAllowedListenersForParentRefs(tcpRoute, gateways, resources) + relevantRoute := t.processAllowedListenersForParentRefs(translatorContext, tcpRoute, gateways) if !relevantRoute { continue } relevantTCPRoutes = append(relevantTCPRoutes, tcpRoute) - t.processTCPRouteParentRefs(tcpRoute, resources, xdsIR) + t.processTCPRouteParentRefs(translatorContext, tcpRoute, resources, xdsIR) } return relevantTCPRoutes } -func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resources *resource.Resources, xdsIR resource.XdsIRMap) { +func (t *Translator) processTCPRouteParentRefs(translatorContext *TranslatorContext, tcpRoute *TCPRouteContext, resources *resource.Resources, xdsIR resource.XdsIRMap) { for _, parentRef := range tcpRoute.ParentRefs { // compute backends if len(tcpRoute.Spec.Rules) != 1 { @@ -1497,7 +1497,7 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour for i := range tcpRoute.Spec.Rules[0].BackendRefs { settingName := irDestinationSettingName(destName, i) backendRefCtx := DirectBackendRef{BackendRef: &tcpRoute.Spec.Rules[0].BackendRefs[i]} - ds, _, err := t.processDestination(settingName, backendRefCtx, parentRef, tcpRoute, resources) + ds, _, err := t.processDestination(translatorContext, settingName, backendRefCtx, parentRef, tcpRoute, resources) // skip adding the route and provide the reason via route status. if err != nil { resolveErrs.Add(err) @@ -1606,7 +1606,7 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour // processDestination translates a backendRef into a destination settings. // If an error occurs during this conversion, an error is returned, and the associated routes are expected to become inactive. // This will result in a direct 500 response for HTTP-based requests. -func (t *Translator) processDestination(name string, backendRefContext BackendRefContext, +func (t *Translator) processDestination(translatorContext *TranslatorContext, name string, backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, resources *resource.Resources, ) (ds *ir.DestinationSetting, unstructuredRef *ir.UnstructuredRef, err status.Error) { var ( @@ -1624,7 +1624,7 @@ func (t *Translator) processDestination(name string, backendRefContext BackendRe backendNamespace := NamespaceDerefOr(backendRef.Namespace, route.GetNamespace()) if !t.isCustomBackendResource(backendRef.Group, KindDerefOr(backendRef.Kind, resource.KindService)) { - err = t.validateBackendRef(backendRefContext, route, resources, backendNamespace, routeType) + err = t.validateBackendRef(translatorContext, backendRefContext, route, resources, backendNamespace, routeType) { // Empty DS means the backend is invalid and an error to fail the associated route. if err != nil { @@ -1648,6 +1648,7 @@ func (t *Translator) processDestination(name string, backendRefContext BackendRe // Process BackendTLSPolicy first to ensure status is set. tls, tlsErr := t.applyBackendTLSSetting( + translatorContext, backendRef.BackendObjectReference, backendNamespace, gwapiv1.ParentReference{ @@ -1667,20 +1668,20 @@ func (t *Translator) processDestination(name string, backendRefContext BackendRe switch KindDerefOr(backendRef.Kind, resource.KindService) { case resource.KindServiceImport: - ds, err = t.processServiceImportDestinationSetting(name, backendRef.BackendObjectReference, backendNamespace, protocol, resources, envoyProxy) + ds, err = t.processServiceImportDestinationSetting(translatorContext, name, backendRef.BackendObjectReference, backendNamespace, protocol, envoyProxy) if err != nil { return emptyDS, nil, err } case resource.KindService: - ds, err = t.processServiceDestinationSetting(name, backendRef.BackendObjectReference, backendNamespace, protocol, resources, envoyProxy) + ds, err = t.processServiceDestinationSetting(translatorContext, name, backendRef.BackendObjectReference, backendNamespace, protocol, envoyProxy) if err != nil { return emptyDS, nil, err } - svc := resources.GetService(backendNamespace, string(backendRef.Name)) + svc := translatorContext.GetService(backendNamespace, string(backendRef.Name)) ds.IPFamily = getServiceIPFamily(svc) ds.PreferLocal = processPreferLocalZone(svc) case egv1a1.KindBackend: - ds = t.processBackendDestinationSetting(name, backendRef.BackendObjectReference, backendNamespace, protocol, resources) + ds = t.processBackendDestinationSetting(translatorContext, name, backendRef.BackendObjectReference, backendNamespace, protocol) default: // Handle custom backend resources defined in extension manager if t.isCustomBackendResource(backendRef.Group, KindDerefOr(backendRef.Kind, resource.KindService)) { @@ -1709,7 +1710,7 @@ func (t *Translator) processDestination(name string, backendRefContext BackendRe ds.TLS = tls var filtersErr error - ds.Filters, filtersErr = t.processDestinationFilters(routeType, backendRefContext, parentRef, route, resources) + ds.Filters, filtersErr = t.processDestinationFilters(translatorContext, routeType, backendRefContext, parentRef, route, resources) if filtersErr != nil { return emptyDS, nil, status.NewRouteStatusError(filtersErr, status.RouteReasonInvalidBackendFilters) } @@ -1759,11 +1760,11 @@ func isHeadlessService(ds *ir.DestinationSetting) bool { } func (t *Translator) processServiceImportDestinationSetting( + translatorContext *TranslatorContext, name string, backendRef gwapiv1.BackendObjectReference, backendNamespace string, protocol ir.AppProtocol, - resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy, ) (*ir.DestinationSetting, status.Error) { var ( @@ -1771,7 +1772,7 @@ func (t *Translator) processServiceImportDestinationSetting( addrType *ir.DestinationAddressType ) - serviceImport := resources.GetServiceImport(backendNamespace, string(backendRef.Name)) + serviceImport := translatorContext.GetServiceImport(backendNamespace, string(backendRef.Name)) var servicePort mcsapiv1a1.ServicePort for _, port := range serviceImport.Spec.Ports { if port.Port == *backendRef.Port { @@ -1786,7 +1787,7 @@ func (t *Translator) processServiceImportDestinationSetting( // Route to endpoints by default if !t.IsEnvoyServiceRouting(envoyProxy) { - endpointSlices := resources.GetEndpointSlicesForBackend(backendNamespace, string(backendRef.Name), resource.KindServiceImport) + endpointSlices := translatorContext.GetEndpointSlicesForBackend(backendNamespace, string(backendRef.Name), resource.KindServiceImport) endpoints, addrType = getIREndpointsFromEndpointSlices(endpointSlices, servicePort.Name, getServicePortProtocol(servicePort.Protocol)) if len(endpoints) == 0 { return nil, status.NewRouteStatusError( @@ -1796,7 +1797,7 @@ func (t *Translator) processServiceImportDestinationSetting( } } else { // Fall back to Service ClusterIP routing - backendIps := resources.GetServiceImport(backendNamespace, string(backendRef.Name)).Spec.IPs + backendIps := translatorContext.GetServiceImport(backendNamespace, string(backendRef.Name)).Spec.IPs for _, ip := range backendIps { ep := ir.NewDestEndpoint(nil, ip, uint32(*backendRef.Port), false, nil) endpoints = append(endpoints, ep) @@ -1813,11 +1814,11 @@ func (t *Translator) processServiceImportDestinationSetting( } func (t *Translator) processServiceDestinationSetting( + translatorContext *TranslatorContext, name string, backendRef gwapiv1.BackendObjectReference, backendNamespace string, protocol ir.AppProtocol, - resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy, ) (*ir.DestinationSetting, status.Error) { var ( @@ -1825,7 +1826,7 @@ func (t *Translator) processServiceDestinationSetting( addrType *ir.DestinationAddressType ) - service := resources.GetService(backendNamespace, string(backendRef.Name)) + service := translatorContext.GetService(backendNamespace, string(backendRef.Name)) var servicePort corev1.ServicePort for _, port := range service.Spec.Ports { if port.Port == *backendRef.Port { @@ -1841,7 +1842,7 @@ func (t *Translator) processServiceDestinationSetting( // Route to endpoints by default if !t.IsEnvoyServiceRouting(envoyProxy) { - endpointSlices := resources.GetEndpointSlicesForBackend(backendNamespace, string(backendRef.Name), KindDerefOr(backendRef.Kind, resource.KindService)) + endpointSlices := translatorContext.GetEndpointSlicesForBackend(backendNamespace, string(backendRef.Name), KindDerefOr(backendRef.Kind, resource.KindService)) endpoints, addrType = getIREndpointsFromEndpointSlices(endpointSlices, servicePort.Name, getServicePortProtocol(servicePort.Protocol)) if len(endpoints) == 0 { return nil, status.NewRouteStatusError( @@ -1914,7 +1915,7 @@ func processPreferLocalZone(svc *corev1.Service) *ir.PreferLocalZone { return nil } -func (t *Translator) processDestinationFilters(routeType gwapiv1.Kind, backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, resources *resource.Resources) (*ir.DestinationFilters, error) { +func (t *Translator) processDestinationFilters(translatorContext *TranslatorContext, routeType gwapiv1.Kind, backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, resources *resource.Resources) (*ir.DestinationFilters, error) { backendFilters := getBackendFilters(routeType, backendRefContext) if backendFilters == nil { return nil, nil @@ -1926,10 +1927,10 @@ func (t *Translator) processDestinationFilters(routeType gwapiv1.Kind, backendRe var err error switch filters := backendFilters.(type) { case []gwapiv1.HTTPRouteFilter: - httpFiltersContext, err = t.ProcessHTTPFilters(parentRef, route, filters, 0, resources) + httpFiltersContext, err = t.ProcessHTTPFilters(translatorContext, parentRef, route, filters, 0, resources) case []gwapiv1.GRPCRouteFilter: - httpFiltersContext, err = t.ProcessGRPCFilters(parentRef, route, filters, resources) + httpFiltersContext, err = t.ProcessGRPCFilters(translatorContext, parentRef, route, filters, resources) if err != nil { return &destFilters, err } @@ -1976,7 +1977,11 @@ func inspectAppProtocolByRouteKind(kind gwapiv1.Kind) ir.AppProtocol { // processAllowedListenersForParentRefs finds out if the route attaches to one of our // Gateways' listeners, and if so, gets the list of listeners that allow it to // attach for each parentRef. -func (t *Translator) processAllowedListenersForParentRefs(routeContext RouteContext, gateways []*GatewayContext, resources *resource.Resources) bool { +func (t *Translator) processAllowedListenersForParentRefs( + translatorContext *TranslatorContext, + routeContext RouteContext, + gateways []*GatewayContext, +) bool { var relevantRoute bool ns := gwapiv1.Namespace(routeContext.GetNamespace()) for _, parentRef := range GetParentReferences(routeContext) { @@ -2009,7 +2014,7 @@ func (t *Translator) processAllowedListenersForParentRefs(routeContext RouteCont for _, listener := range selectedListeners { acceptedKind := routeContext.GetRouteType() if listener.AllowsKind(gwapiv1.RouteGroupKind{Group: GroupPtr(gwapiv1.GroupName), Kind: acceptedKind}) && - listener.AllowsNamespace(resources.GetNamespace(routeContext.GetNamespace())) { + listener.AllowsNamespace(translatorContext.GetNamespace(routeContext.GetNamespace())) { allowedListeners = append(allowedListeners, listener) } } @@ -2164,7 +2169,11 @@ func (t *Translator) processBackendExtensions( return nil } -func getTargetBackendReference(backendRef gwapiv1.BackendObjectReference, backendNamespace string, resources *resource.Resources) gwapiv1.LocalPolicyTargetReferenceWithSectionName { +func getTargetBackendReference( + translatorContext *TranslatorContext, + backendRef gwapiv1.BackendObjectReference, + backendNamespace string, +) gwapiv1.LocalPolicyTargetReferenceWithSectionName { ref := gwapiv1.LocalPolicyTargetReferenceWithSectionName{ LocalPolicyTargetReference: gwapiv1.LocalPolicyTargetReference{ Group: func() gwapiv1.Group { @@ -2188,7 +2197,7 @@ func getTargetBackendReference(backendRef gwapiv1.BackendObjectReference, backen switch { case backendRef.Kind == nil || *backendRef.Kind == resource.KindService: - if service := resources.GetService(backendNamespace, string(backendRef.Name)); service != nil { + if service := translatorContext.GetService(backendNamespace, string(backendRef.Name)); service != nil { for _, port := range service.Spec.Ports { if port.Port == *backendRef.Port { if port.Name != "" { @@ -2200,7 +2209,7 @@ func getTargetBackendReference(backendRef gwapiv1.BackendObjectReference, backen } case *backendRef.Kind == resource.KindServiceImport: - if si := resources.GetServiceImport(backendNamespace, string(backendRef.Name)); si != nil { + if si := translatorContext.GetServiceImport(backendNamespace, string(backendRef.Name)); si != nil { for _, port := range si.Spec.Ports { if port.Port == *backendRef.Port { if port.Name != "" { @@ -2220,16 +2229,16 @@ func getTargetBackendReference(backendRef gwapiv1.BackendObjectReference, backen } func (t *Translator) processBackendDestinationSetting( + translatorContext *TranslatorContext, name string, backendRef gwapiv1.BackendObjectReference, backendNamespace string, protocol ir.AppProtocol, - resources *resource.Resources, ) *ir.DestinationSetting { var dstAddrType *ir.DestinationAddressType addrTypeMap := make(map[ir.DestinationAddressType]int) - backend := resources.GetBackend(backendNamespace, string(backendRef.Name)) + backend := translatorContext.GetBackend(backendNamespace, string(backendRef.Name)) for _, ap := range backend.Spec.AppProtocols { protocol = backendAppProtocolToIRAppProtocol(ap, protocol) } diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index 4dca669f882..d66c9795581 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -50,7 +50,9 @@ const ( oidcHMACSecretKey = "hmac-secret" ) -func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.SecurityPolicy, +func (t *Translator) ProcessSecurityPolicies( + translatorContext *TranslatorContext, + securityPolicies []*egv1a1.SecurityPolicy, gateways []*GatewayContext, routes []RouteContext, resources *resource.Resources, @@ -112,7 +114,7 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security res = append(res, policy) } - t.processSecurityPolicyForRoute(resources, xdsIR, + t.processSecurityPolicyForRoute(translatorContext, resources, xdsIR, routeMap, gatewayRouteMap, policy, currTarget) } } @@ -131,7 +133,7 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security res = append(res, policy) } - t.processSecurityPolicyForRoute(resources, xdsIR, + t.processSecurityPolicyForRoute(translatorContext, resources, xdsIR, routeMap, gatewayRouteMap, policy, currTarget) } } @@ -150,7 +152,7 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security res = append(res, policy) } - t.processSecurityPolicyForGateway(resources, xdsIR, + t.processSecurityPolicyForGateway(translatorContext, resources, xdsIR, gatewayMap, gatewayRouteMap, policy, currTarget) } } @@ -169,7 +171,7 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security res = append(res, policy) } - t.processSecurityPolicyForGateway(resources, xdsIR, + t.processSecurityPolicyForGateway(translatorContext, resources, xdsIR, gatewayMap, gatewayRouteMap, policy, currTarget) } } @@ -185,6 +187,7 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security } func (t *Translator) processSecurityPolicyForRoute( + translatorContext *TranslatorContext, resources *resource.Resources, xdsIR resource.XdsIRMap, routeMap map[policyTargetRouteKey]*policyRouteTargetContext, @@ -271,7 +274,7 @@ func (t *Translator) processSecurityPolicyForRoute( return } - if err := t.translateSecurityPolicyForRoute(policy, targetedRoute, currTarget, resources, xdsIR); err != nil { + if err := t.translateSecurityPolicyForRoute(translatorContext, policy, targetedRoute, currTarget, resources, xdsIR); err != nil { status.SetTranslationErrorForPolicyAncestors(&policy.Status, parentGateways, t.GatewayControllerName, @@ -304,6 +307,7 @@ func (t *Translator) processSecurityPolicyForRoute( } func (t *Translator) processSecurityPolicyForGateway( + translatorContext *TranslatorContext, resources *resource.Resources, xdsIR resource.XdsIRMap, gatewayMap map[types.NamespacedName]*policyGatewayTargetContext, @@ -341,7 +345,7 @@ func (t *Translator) processSecurityPolicyForGateway( return } - if err := t.translateSecurityPolicyForGateway(policy, targetedGateway, currTarget, resources, xdsIR); err != nil { + if err := t.translateSecurityPolicyForGateway(translatorContext, policy, targetedGateway, currTarget, resources, xdsIR); err != nil { status.SetTranslationErrorForPolicyAncestor(&policy.Status, &parentGateway, t.GatewayControllerName, @@ -595,6 +599,7 @@ func resolveSecurityPolicyRouteTargetRef( } func (t *Translator) translateSecurityPolicyForRoute( + translatorContext *TranslatorContext, policy *egv1a1.SecurityPolicy, route RouteContext, target gwapiv1.LocalPolicyTargetReferenceWithSectionName, @@ -616,7 +621,7 @@ func (t *Translator) translateSecurityPolicyForRoute( } if policy.Spec.BasicAuth != nil { - if basicAuth, err = t.buildBasicAuth( + if basicAuth, err = t.buildBasicAuth(translatorContext, policy, resources); err != nil { err = perr.WithMessage(err, "BasicAuth") @@ -625,7 +630,7 @@ func (t *Translator) translateSecurityPolicyForRoute( } if policy.Spec.APIKeyAuth != nil { - if apiKeyAuth, err = t.buildAPIKeyAuth( + if apiKeyAuth, err = t.buildAPIKeyAuth(translatorContext, policy, resources); err != nil { err = perr.WithMessage(err, "APIKeyAuth") @@ -657,6 +662,7 @@ func (t *Translator) translateSecurityPolicyForRoute( var extAuthErr error if policy.Spec.ExtAuth != nil { if extAuth, extAuthErr = t.buildExtAuth( + translatorContext, policy, resources, gtwCtx.envoyProxy); extAuthErr != nil { @@ -668,6 +674,7 @@ func (t *Translator) translateSecurityPolicyForRoute( var oidc *ir.OIDC if policy.Spec.OIDC != nil { if oidc, err = t.buildOIDC( + translatorContext, policy, resources, gtwCtx.envoyProxy); err != nil { @@ -680,6 +687,7 @@ func (t *Translator) translateSecurityPolicyForRoute( var jwt *ir.JWT if policy.Spec.JWT != nil { if jwt, err = t.buildJWT( + translatorContext, policy, resources, gtwCtx.envoyProxy); err != nil { @@ -773,6 +781,7 @@ func (t *Translator) translateSecurityPolicyForRoute( } func (t *Translator) translateSecurityPolicyForGateway( + translatorContext *TranslatorContext, policy *egv1a1.SecurityPolicy, gateway *GatewayContext, target gwapiv1.LocalPolicyTargetReferenceWithSectionName, @@ -798,6 +807,7 @@ func (t *Translator) translateSecurityPolicyForGateway( if policy.Spec.JWT != nil { if jwt, err = t.buildJWT( + translatorContext, policy, resources, gateway.envoyProxy); err != nil { @@ -808,6 +818,7 @@ func (t *Translator) translateSecurityPolicyForGateway( if policy.Spec.OIDC != nil { if oidc, err = t.buildOIDC( + translatorContext, policy, resources, gateway.envoyProxy); err != nil { @@ -817,7 +828,7 @@ func (t *Translator) translateSecurityPolicyForGateway( } if policy.Spec.BasicAuth != nil { - if basicAuth, err = t.buildBasicAuth( + if basicAuth, err = t.buildBasicAuth(translatorContext, policy, resources); err != nil { err = perr.WithMessage(err, "BasicAuth") @@ -826,7 +837,7 @@ func (t *Translator) translateSecurityPolicyForGateway( } if policy.Spec.APIKeyAuth != nil { - if apiKeyAuth, err = t.buildAPIKeyAuth( + if apiKeyAuth, err = t.buildAPIKeyAuth(translatorContext, policy, resources); err != nil { err = perr.WithMessage(err, "APIKeyAuth") @@ -844,6 +855,7 @@ func (t *Translator) translateSecurityPolicyForGateway( if policy.Spec.ExtAuth != nil { if extAuth, extAuthErr = t.buildExtAuth( + translatorContext, policy, resources, gateway.envoyProxy); extAuthErr != nil { @@ -1005,6 +1017,7 @@ func wildcard2regex(wildcard string) string { } func (t *Translator) buildJWT( + translatorContext *TranslatorContext, policy *egv1a1.SecurityPolicy, resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy, @@ -1024,13 +1037,13 @@ func (t *Translator) buildJWT( ExtractFrom: p.ExtractFrom, } if p.RemoteJWKS != nil { - remoteJWKS, err := t.buildRemoteJWKS(policy, p.RemoteJWKS, i, resources, envoyProxy) + remoteJWKS, err := t.buildRemoteJWKS(translatorContext, policy, p.RemoteJWKS, i, resources, envoyProxy) if err != nil { return nil, err } provider.RemoteJWKS = remoteJWKS } else { - localJWKS, err := t.buildLocalJWKS(policy, p.LocalJWKS, resources) + localJWKS, err := t.buildLocalJWKS(translatorContext, policy, p.LocalJWKS) if err != nil { return nil, err } @@ -1130,6 +1143,7 @@ func validateJWTProvider(providers []egv1a1.JWTProvider) error { } func (t *Translator) buildRemoteJWKS( + translatorContext *TranslatorContext, policy *egv1a1.SecurityPolicy, remoteJWKS *egv1a1.RemoteJWKS, index int, @@ -1156,7 +1170,7 @@ func (t *Translator) buildRemoteJWKS( } if len(remoteJWKS.BackendRefs) > 0 { - if rd, err = t.translateExtServiceBackendRefs( + if rd, err = t.translateExtServiceBackendRefs(translatorContext, policy, remoteJWKS.BackendRefs, protocol, resources, envoyProxy, "jwt", index); err != nil { return nil, err } @@ -1185,9 +1199,9 @@ func (t *Translator) buildRemoteJWKS( } func (t *Translator) buildLocalJWKS( + translatorContext *TranslatorContext, policy *egv1a1.SecurityPolicy, localJWKS *egv1a1.LocalJWKS, - resources *resource.Resources, ) (string, error) { jwksType := egv1a1.LocalJWKSTypeInline if localJWKS.Type != nil { @@ -1195,7 +1209,7 @@ func (t *Translator) buildLocalJWKS( } if jwksType == egv1a1.LocalJWKSTypeValueRef { - cm := resources.GetConfigMap(policy.Namespace, string(localJWKS.ValueRef.Name)) + cm := translatorContext.GetConfigMap(policy.Namespace, string(localJWKS.ValueRef.Name)) if cm == nil { return "", fmt.Errorf("local JWKS ConfigMap %s/%s not found", policy.Namespace, localJWKS.ValueRef.Name) } @@ -1220,6 +1234,7 @@ func (t *Translator) buildLocalJWKS( } func (t *Translator) buildOIDC( + translatorContext *TranslatorContext, policy *egv1a1.SecurityPolicy, resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy, @@ -1239,7 +1254,7 @@ func (t *Translator) buildOIDC( err error ) - if provider, err = t.buildOIDCProvider(policy, resources, envoyProxy); err != nil { + if provider, err = t.buildOIDCProvider(translatorContext, policy, resources, envoyProxy); err != nil { return nil, err } @@ -1255,7 +1270,7 @@ func (t *Translator) buildOIDC( clientID = *oidc.ClientID case oidc.ClientIDRef != nil: var clientIDSecret *corev1.Secret - if clientIDSecret, err = t.validateSecretRef(false, from, *oidc.ClientIDRef, resources); err != nil { + if clientIDSecret, err = t.validateSecretRef(translatorContext, false, from, *oidc.ClientIDRef, resources); err != nil { return nil, err } clientIDBytes, ok := clientIDSecret.Data[egv1a1.OIDCClientIDKey] @@ -1268,8 +1283,7 @@ func (t *Translator) buildOIDC( return nil, fmt.Errorf("client ID must be specified in OIDC policy %s/%s", policy.Namespace, policy.Name) } - if clientSecret, err = t.validateSecretRef( - false, from, oidc.ClientSecret, resources); err != nil { + if clientSecret, err = t.validateSecretRef(translatorContext, false, from, oidc.ClientSecret, resources); err != nil { return nil, err } @@ -1316,7 +1330,7 @@ func (t *Translator) buildOIDC( // HMAC secret is generated by the CertGen job and stored in a secret // We need to rotate the HMAC secret in the future, probably the same // way we rotate the certs generated by the CertGen job. - hmacSecret := resources.GetSecret(t.ControllerNamespace, oidcHMACSecretName) + hmacSecret := translatorContext.GetSecret(t.ControllerNamespace, oidcHMACSecretName) if hmacSecret == nil { return nil, fmt.Errorf("HMAC secret %s/%s not found", t.ControllerNamespace, oidcHMACSecretName) } @@ -1375,7 +1389,12 @@ func (t *Translator) buildOIDC( return irOIDC, nil } -func (t *Translator) buildOIDCProvider(policy *egv1a1.SecurityPolicy, resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy) (*ir.OIDCProvider, error) { +func (t *Translator) buildOIDCProvider( + translatorContext *TranslatorContext, + policy *egv1a1.SecurityPolicy, + resources *resource.Resources, + envoyProxy *egv1a1.EnvoyProxy, +) (*ir.OIDCProvider, error) { var ( provider = policy.Spec.OIDC.Provider tokenEndpoint string @@ -1406,7 +1425,8 @@ func (t *Translator) buildOIDCProvider(policy *egv1a1.SecurityPolicy, resources } if len(provider.BackendRefs) > 0 { - if rd, err = t.translateExtServiceBackendRefs(policy, provider.BackendRefs, protocol, resources, envoyProxy, "oidc", 0); err != nil { + if rd, err = t.translateExtServiceBackendRefs(translatorContext, + policy, provider.BackendRefs, protocol, resources, envoyProxy, "oidc", 0); err != nil { return nil, err } } @@ -1658,6 +1678,7 @@ func validateTokenEndpoint(tokenEndpoint string) error { } func (t *Translator) buildAPIKeyAuth( + translatorContext *TranslatorContext, policy *egv1a1.SecurityPolicy, resources *resource.Resources, ) (*ir.APIKeyAuth, error) { @@ -1671,7 +1692,7 @@ func (t *Translator) buildAPIKeyAuth( seenKeys := make(sets.Set[string]) for _, ref := range policy.Spec.APIKeyAuth.CredentialRefs { - credentialsSecret, err := t.validateSecretRef( + credentialsSecret, err := t.validateSecretRef(translatorContext, false, from, ref, resources) if err != nil { return nil, err @@ -1709,6 +1730,7 @@ func (t *Translator) buildAPIKeyAuth( } func (t *Translator) buildBasicAuth( + translatorContext *TranslatorContext, policy *egv1a1.SecurityPolicy, resources *resource.Resources, ) (*ir.BasicAuth, error) { @@ -1723,7 +1745,7 @@ func (t *Translator) buildBasicAuth( kind: resource.KindSecurityPolicy, namespace: policy.Namespace, } - if usersSecret, err = t.validateSecretRef( + if usersSecret, err = t.validateSecretRef(translatorContext, false, from, basicAuth.Users, resources); err != nil { return nil, err } @@ -1771,6 +1793,7 @@ func validateHtpasswdFormat(data []byte) error { } func (t *Translator) buildExtAuth( + translatorContext *TranslatorContext, policy *egv1a1.SecurityPolicy, resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy, @@ -1830,7 +1853,8 @@ func (t *Translator) buildExtAuth( } } - if rd, err = t.translateExtServiceBackendRefs(policy, backendRefs, protocol, resources, envoyProxy, "extauth", 0); err != nil { + if rd, err = t.translateExtServiceBackendRefs(translatorContext, + policy, backendRefs, protocol, resources, envoyProxy, "extauth", 0); err != nil { return nil, err } @@ -1840,7 +1864,7 @@ func (t *Translator) buildExtAuth( // When translated to XDS, the authority is used on the filter level not on the cluster level. // There's no way to translate to XDS and use a different authority for each backendref if authority == "" { - authority = backendRefAuthority(resources, &backendRef.BackendObjectReference, policy) + authority = backendRefAuthority(translatorContext, &backendRef.BackendObjectReference, policy) } } @@ -1893,7 +1917,11 @@ func parseExtAuthTimeout(timeout *gwapiv1.Duration) *metav1.Duration { } } -func backendRefAuthority(resources *resource.Resources, backendRef *gwapiv1.BackendObjectReference, policy *egv1a1.SecurityPolicy) string { +func backendRefAuthority( + translatorContext *TranslatorContext, + backendRef *gwapiv1.BackendObjectReference, + policy *egv1a1.SecurityPolicy, +) string { if backendRef == nil { return "" } @@ -1901,7 +1929,7 @@ func backendRefAuthority(resources *resource.Resources, backendRef *gwapiv1.Back backendNamespace := NamespaceDerefOr(backendRef.Namespace, policy.Namespace) backendKind := KindDerefOr(backendRef.Kind, resource.KindService) if backendKind == resource.KindBackend { - backend := resources.GetBackend(backendNamespace, string(backendRef.Name)) + backend := translatorContext.GetBackend(backendNamespace, string(backendRef.Name)) if backend != nil { // TODO: exists multi FQDN endpoints? for _, ep := range backend.Spec.Endpoints { diff --git a/internal/gatewayapi/securitypolicy_test.go b/internal/gatewayapi/securitypolicy_test.go index 16067ef8a75..490bbd31437 100644 --- a/internal/gatewayapi/securitypolicy_test.go +++ b/internal/gatewayapi/securitypolicy_test.go @@ -879,6 +879,7 @@ func hasParentFalseCondition(p *egv1a1.SecurityPolicy) bool { // --- TCP branch: validateSecurityPolicyForTCP(...) returns err -> SetTranslationErrorForPolicyAncestors(...) + return func Test_SecurityPolicy_TCP_Invalid_setsStatus_and_returns(t *testing.T) { tr := &Translator{GatewayControllerName: "gateway.envoyproxy.io/gatewayclass-controller"} + trContext := &TranslatorContext{} // Create an invalid TCP policy (has CORS which is not allowed for TCP) policy := sp("default", "bad-tcp") @@ -936,9 +937,10 @@ func Test_SecurityPolicy_TCP_Invalid_setsStatus_and_returns(t *testing.T) { gatewayRouteMap := make(map[string]map[string]sets.Set[string]) resources := resource.NewResources() xdsIR := make(resource.XdsIRMap) + trContext.SetServices(resources.Services) // Process the policy - this should set error status - tr.processSecurityPolicyForRoute(resources, xdsIR, routeMap, gatewayRouteMap, policy, target) + tr.processSecurityPolicyForRoute(trContext, resources, xdsIR, routeMap, gatewayRouteMap, policy, target) // Assert that the policy has a False condition (error was set) require.True(t, hasParentFalseCondition(policy)) @@ -947,6 +949,7 @@ func Test_SecurityPolicy_TCP_Invalid_setsStatus_and_returns(t *testing.T) { // --- non-TCP branch: malformed CIDR should return err -> SetTranslationErrorForPolicyAncestors(...) + return func Test_SecurityPolicy_HTTP_Invalid_setsStatus_and_returns(t *testing.T) { tr := &Translator{GatewayControllerName: "gateway.envoyproxy.io/gatewayclass-controller"} + trContext := &TranslatorContext{} // Create an invalid HTTP policy (malformed CIDR) policy := sp("default", "bad-http") @@ -1010,9 +1013,10 @@ func Test_SecurityPolicy_HTTP_Invalid_setsStatus_and_returns(t *testing.T) { gatewayRouteMap := make(map[string]map[string]sets.Set[string]) resources := resource.NewResources() xdsIR := make(resource.XdsIRMap) + trContext.SetServices(resources.Services) // Process the policy - this should set error status - tr.processSecurityPolicyForRoute(resources, xdsIR, routeMap, gatewayRouteMap, policy, target) + tr.processSecurityPolicyForRoute(trContext, resources, xdsIR, routeMap, gatewayRouteMap, policy, target) // Assert that the policy has a False condition (error was set) require.True(t, hasParentFalseCondition(policy)) diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-dns-lookup-family.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-dns-lookup-family.in.yaml index 91d1f3b3b5a..3bab4e55653 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-dns-lookup-family.in.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-dns-lookup-family.in.yaml @@ -140,16 +140,6 @@ backends: - fqdn: hostname: backend-v3.gateway-conformance-infra.svc.cluster.local port: 8080 - - apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: Backend - metadata: - name: backend-fqdn - namespace: default - spec: - endpoints: - - fqdn: - hostname: grpc-infra-backend-v1.gateway-conformance-infra.svc.cluster.local - port: 8080 backendTrafficPolicies: - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-dns-lookup-family.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-dns-lookup-family.out.yaml index e543d2d1618..1818b7044d1 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-dns-lookup-family.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-dns-lookup-family.out.yaml @@ -80,23 +80,6 @@ backends: reason: Accepted status: "True" type: Accepted -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: Backend - metadata: - name: backend-fqdn - namespace: default - spec: - endpoints: - - fqdn: - hostname: grpc-infra-backend-v1.gateway-conformance-infra.svc.cluster.local - port: 8080 - status: - conditions: - - lastTransitionTime: null - message: The Backend was accepted - reason: Accepted - status: "True" - type: Accepted envoyExtensionPolicies: - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyExtensionPolicy diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-multiple-targets-targetselector.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-multiple-targets-targetselector.out.yaml index dfec216ac04..d6f9e247065 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-multiple-targets-targetselector.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-multiple-targets-targetselector.out.yaml @@ -221,7 +221,6 @@ xdsIR: - host: 7.7.7.7 port: 8080 metadata: - kind: Service name: service-1 namespace: default sectionName: "8080" diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-endpointoverride-loadbalancer-multiple-mixed.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-endpointoverride-loadbalancer-multiple-mixed.out.yaml index 8390fde9d53..475b44b026c 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-endpointoverride-loadbalancer-multiple-mixed.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-endpointoverride-loadbalancer-multiple-mixed.out.yaml @@ -182,7 +182,6 @@ xdsIR: - host: 7.7.7.7 port: 8080 metadata: - kind: Service name: service-1 namespace: default sectionName: "8080" diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-endpointoverride-loadbalancer-single-header.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-endpointoverride-loadbalancer-single-header.out.yaml index d4bd22fa00e..fbfa11622da 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-endpointoverride-loadbalancer-single-header.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-endpointoverride-loadbalancer-single-header.out.yaml @@ -182,7 +182,6 @@ xdsIR: - host: 7.7.7.7 port: 8080 metadata: - kind: Service name: service-1 namespace: default sectionName: "8080" diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-endpointoverride-loadbalancer.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-endpointoverride-loadbalancer.out.yaml index 97bd97f6ec4..17b2756774b 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-endpointoverride-loadbalancer.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-endpointoverride-loadbalancer.out.yaml @@ -219,7 +219,6 @@ xdsIR: - host: 7.7.7.7 port: 8080 metadata: - kind: Service name: service-2 namespace: default sectionName: "8080" @@ -251,7 +250,6 @@ xdsIR: - host: 7.7.7.7 port: 8080 metadata: - kind: Service name: service-1 namespace: default sectionName: "8080" diff --git a/internal/gatewayapi/testdata/extensions/httproute-with-custom-backend-mixed-multiple.out.yaml b/internal/gatewayapi/testdata/extensions/httproute-with-custom-backend-mixed-multiple.out.yaml index 45e610535f5..2ebf5b58c7e 100644 --- a/internal/gatewayapi/testdata/extensions/httproute-with-custom-backend-mixed-multiple.out.yaml +++ b/internal/gatewayapi/testdata/extensions/httproute-with-custom-backend-mixed-multiple.out.yaml @@ -170,7 +170,6 @@ xdsIR: - host: 7.7.7.7 port: 8080 metadata: - kind: Service name: service-1 namespace: default sectionName: "8080" @@ -233,7 +232,6 @@ xdsIR: - host: 7.7.7.7 port: 8080 metadata: - kind: Service name: service-2 namespace: default sectionName: "8080" diff --git a/internal/gatewayapi/testdata/extensions/httproute-with-custom-backend-mixed.out.yaml b/internal/gatewayapi/testdata/extensions/httproute-with-custom-backend-mixed.out.yaml index 73bc6e82ad7..a2bc2dc8585 100644 --- a/internal/gatewayapi/testdata/extensions/httproute-with-custom-backend-mixed.out.yaml +++ b/internal/gatewayapi/testdata/extensions/httproute-with-custom-backend-mixed.out.yaml @@ -162,7 +162,6 @@ xdsIR: - host: 7.7.7.7 port: 8080 metadata: - kind: Service name: service-1 namespace: default sectionName: "8080" @@ -209,7 +208,6 @@ xdsIR: - host: 7.7.7.7 port: 8080 metadata: - kind: Service name: service-2 namespace: default sectionName: "8080" diff --git a/internal/gatewayapi/testdata/gateway-namespace-mode-infra-httproute.out.yaml b/internal/gatewayapi/testdata/gateway-namespace-mode-infra-httproute.out.yaml index 7352cc4043b..7a81864dbd9 100644 --- a/internal/gatewayapi/testdata/gateway-namespace-mode-infra-httproute.out.yaml +++ b/internal/gatewayapi/testdata/gateway-namespace-mode-infra-httproute.out.yaml @@ -330,7 +330,6 @@ xdsIR: - host: 7.7.7.7 port: 8080 metadata: - kind: Service name: service-1 namespace: default sectionName: "8080" @@ -405,7 +404,6 @@ xdsIR: - host: 7.7.7.7 port: 8080 metadata: - kind: Service name: service-2 namespace: default sectionName: "8080" diff --git a/internal/gatewayapi/translator.go b/internal/gatewayapi/translator.go index cf943962ce3..63ee239df1a 100644 --- a/internal/gatewayapi/translator.go +++ b/internal/gatewayapi/translator.go @@ -220,6 +220,16 @@ func newTranslateResult( func (t *Translator) Translate(resources *resource.Resources) (*TranslateResult, error) { var errs error + translatorContext := &TranslatorContext{} + translatorContext.SetNamespaces(resources.Namespaces) + translatorContext.SetServices(resources.Services) + translatorContext.SetServiceImports(resources.ServiceImports) + translatorContext.SetBackends(resources.Backends) + translatorContext.SetSecrets(resources.Secrets) + translatorContext.SetConfigMaps(resources.ConfigMaps) + translatorContext.SetClusterTrustBundles(resources.ClusterTrustBundles) + translatorContext.SetEndpointSlicesForBackend(resources.EndpointSlices) + // Get Gateways belonging to our GatewayClass. acceptedGateways, failedGateways := t.GetRelevantGateways(resources) @@ -229,7 +239,7 @@ func (t *Translator) Translate(resources *resource.Resources) (*TranslateResult, xdsIR, infraIR := t.InitIRs(acceptedGateways) // Process all Listeners for all relevant Gateways. - t.ProcessListeners(acceptedGateways, xdsIR, infraIR, resources) + t.ProcessListeners(translatorContext, acceptedGateways, xdsIR, infraIR, resources) // Process EnvoyPatchPolicies t.ProcessEnvoyPatchPolicies(resources.EnvoyPatchPolicies, xdsIR) @@ -241,22 +251,22 @@ func (t *Translator) Translate(resources *resource.Resources) (*TranslateResult, backends := t.ProcessBackends(resources.Backends, resources.BackendTLSPolicies) // Process all relevant HTTPRoutes. - httpRoutes := t.ProcessHTTPRoutes(resources.HTTPRoutes, acceptedGateways, resources, xdsIR) + httpRoutes := t.ProcessHTTPRoutes(translatorContext, resources.HTTPRoutes, acceptedGateways, resources, xdsIR) // Process all relevant GRPCRoutes. - grpcRoutes := t.ProcessGRPCRoutes(resources.GRPCRoutes, acceptedGateways, resources, xdsIR) + grpcRoutes := t.ProcessGRPCRoutes(translatorContext, resources.GRPCRoutes, acceptedGateways, resources, xdsIR) // Process all relevant TLSRoutes. - tlsRoutes := t.ProcessTLSRoutes(resources.TLSRoutes, acceptedGateways, resources, xdsIR) + tlsRoutes := t.ProcessTLSRoutes(translatorContext, resources.TLSRoutes, acceptedGateways, resources, xdsIR) // Process all relevant TCPRoutes. - tcpRoutes := t.ProcessTCPRoutes(resources.TCPRoutes, acceptedGateways, resources, xdsIR) + tcpRoutes := t.ProcessTCPRoutes(translatorContext, resources.TCPRoutes, acceptedGateways, resources, xdsIR) // Process all relevant UDPRoutes. - udpRoutes := t.ProcessUDPRoutes(resources.UDPRoutes, acceptedGateways, resources, xdsIR) + udpRoutes := t.ProcessUDPRoutes(translatorContext, resources.UDPRoutes, acceptedGateways, resources, xdsIR) // Process ClientTrafficPolicies - clientTrafficPolicies := t.ProcessClientTrafficPolicies(resources, acceptedGateways, xdsIR, infraIR) + clientTrafficPolicies := t.ProcessClientTrafficPolicies(translatorContext, resources, acceptedGateways, xdsIR, infraIR) routes := make([]RouteContext, len(httpRoutes)+len(grpcRoutes)+len(tlsRoutes)+len(tcpRoutes)+len(udpRoutes)) offset := 0 @@ -281,15 +291,15 @@ func (t *Translator) Translate(resources *resource.Resources) (*TranslateResult, } // Process BackendTrafficPolicies - backendTrafficPolicies := t.ProcessBackendTrafficPolicies( + backendTrafficPolicies := t.ProcessBackendTrafficPolicies(translatorContext, resources, acceptedGateways, routes, xdsIR) // Process SecurityPolicies - securityPolicies := t.ProcessSecurityPolicies( + securityPolicies := t.ProcessSecurityPolicies(translatorContext, resources.SecurityPolicies, acceptedGateways, routes, resources, xdsIR) // Process EnvoyExtensionPolicies - envoyExtensionPolicies := t.ProcessEnvoyExtensionPolicies( + envoyExtensionPolicies := t.ProcessEnvoyExtensionPolicies(translatorContext, resources.EnvoyExtensionPolicies, acceptedGateways, routes, resources, xdsIR) extServerPolicies, err := t.ProcessExtensionServerPolicies( @@ -299,7 +309,7 @@ func (t *Translator) Translate(resources *resource.Resources) (*TranslateResult, } // Process global resources that are not tied to a specific listener or route - if err := t.ProcessGlobalResources(resources, xdsIR, acceptedGateways); err != nil { + if err := t.ProcessGlobalResources(translatorContext, resources, xdsIR, acceptedGateways); err != nil { errs = errors.Join(errs, err) } diff --git a/internal/gatewayapi/validate.go b/internal/gatewayapi/validate.go index 699e3c41e8f..0df6f2bf46f 100644 --- a/internal/gatewayapi/validate.go +++ b/internal/gatewayapi/validate.go @@ -26,7 +26,7 @@ import ( "github.com/envoyproxy/gateway/internal/gatewayapi/status" ) -func (t *Translator) validateBackendRef(backendRefContext BackendRefContext, route RouteContext, +func (t *Translator) validateBackendRef(translatorContext *TranslatorContext, backendRefContext BackendRefContext, route RouteContext, resources *resource.Resources, backendNamespace string, routeKind gwapiv1.Kind, ) status.Error { backendRef := backendRefContext.GetBackendRef() @@ -55,15 +55,15 @@ func (t *Translator) validateBackendRef(backendRefContext BackendRefContext, rou backendRefKind := KindDerefOr(backendRef.Kind, resource.KindService) switch backendRefKind { case resource.KindService: - if err := validateBackendRefService(backendRef.BackendObjectReference, resources, backendNamespace, protocol); err != nil { + if err := validateBackendRefService(translatorContext, backendRef.BackendObjectReference, backendNamespace, protocol); err != nil { return err } case resource.KindServiceImport: - if err := t.validateBackendServiceImport(backendRef.BackendObjectReference, resources, backendNamespace, protocol); err != nil { + if err := t.validateBackendServiceImport(translatorContext, backendRef.BackendObjectReference, backendNamespace, protocol); err != nil { return err } case egv1a1.KindBackend: - if err := t.validateBackendRefBackend(backendRef.BackendObjectReference, resources, backendNamespace, false); err != nil { + if err := t.validateBackendRefBackend(translatorContext, backendRef.BackendObjectReference, resources, backendNamespace, false); err != nil { return err } } @@ -181,10 +181,10 @@ func (t *Translator) validateBackendPort(backendRef *gwapiv1a2.BackendRef) statu return nil } -func validateBackendRefService(backendRef gwapiv1.BackendObjectReference, resources *resource.Resources, +func validateBackendRefService(translatorContext *TranslatorContext, backendRef gwapiv1.BackendObjectReference, serviceNamespace string, protocol corev1.Protocol, ) status.Error { - service := resources.GetService(serviceNamespace, string(backendRef.Name)) + service := translatorContext.GetService(serviceNamespace, string(backendRef.Name)) if service == nil { return status.NewRouteStatusError( fmt.Errorf("service %s/%s not found", serviceNamespace, string(backendRef.Name)), @@ -207,10 +207,13 @@ func validateBackendRefService(backendRef gwapiv1.BackendObjectReference, resour return nil } -func (t *Translator) validateBackendServiceImport(backendRef gwapiv1.BackendObjectReference, resources *resource.Resources, - serviceImportNamespace string, protocol corev1.Protocol, +func (t *Translator) validateBackendServiceImport( + translatorContext *TranslatorContext, + backendRef gwapiv1.BackendObjectReference, + serviceImportNamespace string, + protocol corev1.Protocol, ) status.Error { - serviceImport := resources.GetServiceImport(serviceImportNamespace, string(backendRef.Name)) + serviceImport := translatorContext.GetServiceImport(serviceImportNamespace, string(backendRef.Name)) if serviceImport == nil { return status.NewRouteStatusError( fmt.Errorf("service import %s/%s not found", serviceImportNamespace, backendRef.Name), @@ -235,7 +238,10 @@ func (t *Translator) validateBackendServiceImport(backendRef gwapiv1.BackendObje return nil } -func (t *Translator) validateBackendRefBackend(backendRef gwapiv1.BackendObjectReference, resources *resource.Resources, +func (t *Translator) validateBackendRefBackend( + translatorContext *TranslatorContext, + backendRef gwapiv1.BackendObjectReference, + resources *resource.Resources, backendNamespace string, allowUDS bool, ) status.Error { if !t.BackendEnabled { @@ -245,7 +251,7 @@ func (t *Translator) validateBackendRefBackend(backendRef gwapiv1.BackendObjectR ) } - backend := resources.GetBackend(backendNamespace, string(backendRef.Name)) + backend := translatorContext.GetBackend(backendNamespace, string(backendRef.Name)) if backend == nil { return status.NewRouteStatusError( fmt.Errorf("Backend %s/%s not found", backendNamespace, backendRef.Name), @@ -352,7 +358,11 @@ func (t *Translator) validateAllowedNamespaces(listener *ListenerContext) { } } -func (t *Translator) validateTerminateModeAndGetTLSSecrets(listener *ListenerContext, resources *resource.Resources) ([]*corev1.Secret, []*x509.Certificate) { +func (t *Translator) validateTerminateModeAndGetTLSSecrets( + translatorContext *TranslatorContext, + listener *ListenerContext, + resources *resource.Resources, +) ([]*corev1.Secret, []*x509.Certificate) { if len(listener.TLS.CertificateRefs) == 0 { status.SetGatewayListenerStatusCondition(listener.gateway.Gateway, listener.listenerStatusIdx, @@ -419,7 +429,7 @@ func (t *Translator) validateTerminateModeAndGetTLSSecrets(listener *ListenerCon secretNamespace = string(*certificateRef.Namespace) } - secret := resources.GetSecret(secretNamespace, string(certificateRef.Name)) + secret := translatorContext.GetSecret(secretNamespace, string(certificateRef.Name)) if secret == nil { status.SetGatewayListenerStatusCondition(listener.gateway.Gateway, @@ -471,7 +481,11 @@ func (t *Translator) validateTerminateModeAndGetTLSSecrets(listener *ListenerCon return secrets, certs } -func (t *Translator) validateTLSConfiguration(listener *ListenerContext, resources *resource.Resources) { +func (t *Translator) validateTLSConfiguration( + translatorContext *TranslatorContext, + listener *ListenerContext, + resources *resource.Resources, +) { switch listener.Protocol { case gwapiv1.HTTPProtocolType, gwapiv1.UDPProtocolType, gwapiv1.TCPProtocolType: if listener.TLS != nil { @@ -506,7 +520,7 @@ func (t *Translator) validateTLSConfiguration(listener *ListenerContext, resourc break } - secrets, certs := t.validateTerminateModeAndGetTLSSecrets(listener, resources) + secrets, certs := t.validateTerminateModeAndGetTLSSecrets(translatorContext, listener, resources) listener.SetTLSSecrets(secrets) listener.certDNSNames = make([]string, 0) @@ -550,7 +564,7 @@ func (t *Translator) validateTLSConfiguration(listener *ListenerContext, resourc ) break } - secrets, _ := t.validateTerminateModeAndGetTLSSecrets(listener, resources) + secrets, _ := t.validateTerminateModeAndGetTLSSecrets(translatorContext, listener, resources) listener.SetTLSSecrets(secrets) } } @@ -840,6 +854,7 @@ func (t *Translator) validateHostname(hostname string) error { // // nolint:unparam func (t *Translator) validateSecretRef( + translatorContext *TranslatorContext, allowCrossNamespace bool, from crossNamespaceFrom, secretObjRef gwapiv1.SecretObjectReference, @@ -853,7 +868,7 @@ func (t *Translator) validateSecretRef( if secretObjRef.Namespace != nil { secretNamespace = string(*secretObjRef.Namespace) } - secret := resources.GetSecret(secretNamespace, string(secretObjRef.Name)) + secret := translatorContext.GetSecret(secretNamespace, string(secretObjRef.Name)) if secret == nil { return nil, fmt.Errorf( @@ -864,6 +879,7 @@ func (t *Translator) validateSecretRef( } func (t *Translator) validateConfigMapRef( + translatorContext *TranslatorContext, allowCrossNamespace bool, from crossNamespaceFrom, secretObjRef gwapiv1.SecretObjectReference, @@ -877,7 +893,7 @@ func (t *Translator) validateConfigMapRef( if secretObjRef.Namespace != nil { configMapNamespace = string(*secretObjRef.Namespace) } - configMap := resources.GetConfigMap(configMapNamespace, string(secretObjRef.Name)) + configMap := translatorContext.GetConfigMap(configMapNamespace, string(secretObjRef.Name)) if configMap == nil { return nil, fmt.Errorf( @@ -950,6 +966,7 @@ func (t *Translator) validateSecretObjectRef( // 5. The cross-namespace reference is permitted by the ReferenceGrants if the // namespace is different from the policy's namespace. func (t *Translator) validateExtServiceBackendReference( + translatorContext *TranslatorContext, backendRef *gwapiv1.BackendObjectReference, ownerNamespace string, policyKind string, @@ -973,7 +990,7 @@ func (t *Translator) validateExtServiceBackendReference( case resource.KindService: // check if the service is valid serviceNamespace := NamespaceDerefOr(backendRef.Namespace, ownerNamespace) - service := resources.GetService(serviceNamespace, string(backendRef.Name)) + service := translatorContext.GetService(serviceNamespace, string(backendRef.Name)) if service == nil { return fmt.Errorf("service %s/%s not found", serviceNamespace, backendRef.Name) } @@ -996,7 +1013,7 @@ func (t *Translator) validateExtServiceBackendReference( case resource.KindServiceImport: // check if the service import is valid serviceImportNamespace := NamespaceDerefOr(backendRef.Namespace, ownerNamespace) - serviceImport := resources.GetServiceImport(serviceImportNamespace, string(backendRef.Name)) + serviceImport := translatorContext.GetServiceImport(serviceImportNamespace, string(backendRef.Name)) if serviceImport == nil { return fmt.Errorf("serviceimport %s/%s not found", serviceImportNamespace, backendRef.Name) } @@ -1018,7 +1035,7 @@ func (t *Translator) validateExtServiceBackendReference( } case egv1a1.KindBackend: backendNamespace := NamespaceDerefOr(backendRef.Namespace, ownerNamespace) - backend := resources.GetBackend(backendNamespace, string(backendRef.Name)) + backend := translatorContext.GetBackend(backendNamespace, string(backendRef.Name)) if backend == nil { return fmt.Errorf("backend %s/%s not found", backendNamespace, backendRef.Name) } diff --git a/test/gobench/translate_test.go b/test/gobench/translate_test.go index ee2410d686c..8960212eb44 100644 --- a/test/gobench/translate_test.go +++ b/test/gobench/translate_test.go @@ -7,11 +7,17 @@ package fuzz import ( "fmt" + "io" "strings" "testing" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/cmd/egctl" + "github.com/envoyproxy/gateway/internal/gatewayapi" "github.com/envoyproxy/gateway/internal/gatewayapi/resource" + "github.com/envoyproxy/gateway/internal/logging" ) // Reused YAML snippets. @@ -177,6 +183,37 @@ spec: timeout: http: requestReceivedTimeout: 30s +` + envoyExtensionPolicyYAML = `--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyExtensionPolicy +metadata: + name: envoy-extension-policy + namespace: default +spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: backend + extProc: + - backendRefs: + - kind: Service + name: myExtProc + port: 3000 + messageTimeout: 5s +--- +apiVersion: v1 +kind: Service +metadata: + name: myExtProc + namespace: default +spec: + clusterIP: 10.11.12.13 + ports: + - port: 3000 + name: http + protocol: TCP + targetPort: 3000 ` ) @@ -195,15 +232,17 @@ spec: - group: gateway.networking.k8s.io kind: HTTPRoute name: backend-%d - cors: - allowOrigins: - - "https://www.example-%d.com" - allowMethods: - - GET - - POST - allowHeaders: - - "Content-Type" -`, i, i, i)) + jwt: + providers: + - name: local-jwks-%d + issuer: https://one.example.com + localJWKS: + type: ValueRef + valueRef: + group: "" + kind: ConfigMap + name: jwks-cm-%d +`, i, i, i, i)) } return sb.String() } @@ -232,6 +271,48 @@ spec: return sb.String() } +func genEnvoyExtensionPolicies(n int) string { + var sb strings.Builder + for i := 0; i < n; i++ { + sb.WriteString(fmt.Sprintf(`--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyExtensionPolicy +metadata: + name: envoy-extension-policy-%d + namespace: default +spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: backend-%d + extProc: + - backendRefs: + - kind: Service + name: myExtProc + port: 3000 + messageTimeout: 5s +`, i, i)) + } + return sb.String() +} + +// Helpers for benchmark Secret/ConfigMap generation. +func genJWKSConfigMaps(n int) string { + var sb strings.Builder + for i := 0; i < n; i++ { + sb.WriteString(fmt.Sprintf(`--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: jwks-cm-%d + namespace: default +data: + local.jwt: '{"keys": [{"kty": "RSA","n": "some-modulus","e": "AQAB","kid": "example1-key"}]}' +`, i)) + } + return sb.String() +} + // Helpers for benchmark route generation. func genHTTPRoutes(n int) string { var sb strings.Builder @@ -249,9 +330,9 @@ spec: - "www.example-%d.com" rules: - backendRefs: - - name: provided-backend + - name: service-backend-%d port: 8000 -`, i, i)) +`, i, i, i)) } return sb.String() } @@ -277,9 +358,9 @@ spec: service: com.example.Service%d method: Call backendRefs: - - name: provided-backend + - name: service-backend-%d port: 9000 -`, i, i, i)) +`, i, i, i, i)) } return sb.String() } @@ -299,9 +380,56 @@ spec: sectionName: udp rules: - backendRefs: - - name: provided-backend + - name: service-backend-%d port: %d -`, i, 3000+i)) +`, i, i, 3000+i)) + } + return sb.String() +} + +func genService(n int) string { + var sb strings.Builder + for i := 0; i < n; i++ { + sb.WriteString(fmt.Sprintf(`--- +apiVersion: v1 +kind: Service +metadata: + name: service-backend-%d + namespace: default +spec: + clusterIP: 10.11.12.13 + ports: + - port: 8000 + name: http + protocol: TCP + targetPort: 8000 +`, i)) + } + return sb.String() +} + +func genEndpointSlice(n int) string { + var sb strings.Builder + for i := 0; i < n; i++ { + sb.WriteString(fmt.Sprintf(`--- +apiVersion: discovery.k8s.io/v1 +kind: EndpointSlice +metadata: + name: service-backend-%d-slice + namespace: default + labels: + kubernetes.io/service-name: service-backend-%d +addressType: IPv4 +ports: + - name: http + protocol: TCP + port: 8000 +endpoints: + - addresses: + - 192.168.1.1 + conditions: + ready: true +`, i, i)) } return sb.String() } @@ -313,22 +441,28 @@ func BenchmarkGatewayAPItoXDS(b *testing.B) { yaml string } medium := baseYAML + backendYAML + tlsSecretYAML + clientTrafficPolicyYAML + - genHTTPRoutes(50) + + genHTTPRoutes(200) + genGRPCRoutes(25) + genUDPRoutes(10) + + genJWKSConfigMaps(50) + genSecurityPolicies(50) + - genBackendTrafficPolicies(50) + genBackendTrafficPolicies(50) + + genEnvoyExtensionPolicies(50) + + genService(200) large := baseYAML + backendYAML + tlsSecretYAML + clientTrafficPolicyYAML + - genHTTPRoutes(500) + + genHTTPRoutes(2000) + genGRPCRoutes(250) + genUDPRoutes(100) + + genJWKSConfigMaps(500) + genSecurityPolicies(500) + - genBackendTrafficPolicies(500) + genBackendTrafficPolicies(500) + + genEnvoyExtensionPolicies(500) + + genService(2000) cases := []benchCase{ { name: "small", - yaml: baseYAML + httpRouteYAML + backendYAML + tlsSecretYAML + securityPolicyYAML + backendTrafficPolicyYAML + clientTrafficPolicyYAML, + yaml: baseYAML + httpRouteYAML + backendYAML + tlsSecretYAML + securityPolicyYAML + backendTrafficPolicyYAML + clientTrafficPolicyYAML + envoyExtensionPolicyYAML, }, { name: "medium", @@ -357,3 +491,74 @@ func BenchmarkGatewayAPItoXDS(b *testing.B) { }) } } + +// Benchmark cases: small / medium / large. +// Focus on Gateway API translation performance. +// Since endpoint retrieval can become a major bottleneck due to repeated calls, +// perform translation which endpoint fetching is required. +func BenchmarkGatewayAPITranslator(b *testing.B) { + type benchCase struct { + name string + yaml string + } + medium := baseYAML + backendYAML + tlsSecretYAML + clientTrafficPolicyYAML + + genHTTPRoutes(200) + + genGRPCRoutes(25) + + genUDPRoutes(10) + + genJWKSConfigMaps(50) + + genSecurityPolicies(50) + + genBackendTrafficPolicies(50) + + genEnvoyExtensionPolicies(50) + + genService(200) + + genEndpointSlice(200) + large := baseYAML + backendYAML + tlsSecretYAML + clientTrafficPolicyYAML + + genHTTPRoutes(2000) + + genGRPCRoutes(250) + + genUDPRoutes(100) + + genJWKSConfigMaps(500) + + genSecurityPolicies(500) + + genBackendTrafficPolicies(500) + + genEnvoyExtensionPolicies(500) + + genService(2000) + + genEndpointSlice(2000) + + cases := []benchCase{ + { + name: "small", + yaml: baseYAML + httpRouteYAML + backendYAML + tlsSecretYAML + securityPolicyYAML + backendTrafficPolicyYAML + clientTrafficPolicyYAML + envoyExtensionPolicyYAML, + }, + { + name: "medium", + yaml: medium, + }, + { + name: "large", + yaml: large, + }, + } + + for _, tc := range cases { + b.Run(tc.name, func(b *testing.B) { + rs, err := resource.LoadResourcesFromYAMLBytes([]byte(tc.yaml), true) + if err != nil { + b.Fatalf("load: %v", err) + } + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + translator := &gatewayapi.Translator{ + GatewayControllerName: string(rs.GatewayClass.Spec.ControllerName), + GatewayClassName: gwapiv1.ObjectName(rs.GatewayClass.Name), + GlobalRateLimitEnabled: true, + EndpointRoutingDisabled: false, + EnvoyPatchPolicyEnabled: true, + BackendEnabled: true, + Logger: logging.DefaultLogger(io.Discard, egv1a1.LogLevelInfo), + } + // gatewayapi.Translate errors are ignored in this benchmark, + // those errors are not relevant to the scope of the benchmark. + _, _ = translator.Translate(rs) + } + }) + } +} diff --git a/tools/make/golang.mk b/tools/make/golang.mk index 8a5e5ff748b..7e53a0211c4 100644 --- a/tools/make/golang.mk +++ b/tools/make/golang.mk @@ -16,6 +16,8 @@ endif GO_VERSION = $(shell grep -oE "^go [[:digit:]]*\.[[:digit:]]*" go.mod | cut -d' ' -f2) +GO_BENCH_TESTNAME ?= ^BenchmarkGatewayAPItoXDS$$ + # Build the target binary in target platform. # The pattern of build.% is `build.{Platform}.{Command}`. # If we want to build envoy-gateway in linux amd64 platform, @@ -84,7 +86,7 @@ go.test.cel: manifests # Run the CEL validation tests .PHONY: go.test.benchmark go.test.benchmark: ## Run benchmark tests for translation performance @$(LOG_TARGET) - go test -timeout=15m -run='^$$' -bench=. -benchmem -benchtime=1x -count=6 ./test/gobench + go test -timeout=15m -run='^$$' -bench='$(GO_BENCH_TESTNAME)' -benchmem -benchtime=1x -count=6 ./test/gobench .PHONY: go.test.clean go.test.clean: # Clean go test cache