From 5dfbd4bc03974c30ffce068ec52dab07018d77f9 Mon Sep 17 00:00:00 2001 From: jukie <10012479+jukie@users.noreply.github.com> Date: Wed, 15 Oct 2025 19:21:10 -0600 Subject: [PATCH 01/13] API: Add WeightedZones to PreferLocalZones Signed-off-by: jukie <10012479+jukie@users.noreply.github.com> --- api/v1alpha1/loadbalancer_types.go | 20 + api/v1alpha1/zz_generated.deepcopy.go | 675 +----------------- ....envoyproxy.io_backendtrafficpolicies.yaml | 28 + ....envoyproxy.io_envoyextensionpolicies.yaml | 28 + .../gateway.envoyproxy.io_envoyproxies.yaml | 118 +++ ...ateway.envoyproxy.io_securitypolicies.yaml | 112 +++ ....envoyproxy.io_backendtrafficpolicies.yaml | 28 + ....envoyproxy.io_envoyextensionpolicies.yaml | 28 + .../gateway.envoyproxy.io_envoyproxies.yaml | 118 +++ ...ateway.envoyproxy.io_securitypolicies.yaml | 112 +++ site/content/en/latest/api/extension_types.md | 15 + test/helm/gateway-crds-helm/all.out.yaml | 286 ++++++++ .../envoy-gateway-crds.out.yaml | 286 ++++++++ 13 files changed, 1209 insertions(+), 645 deletions(-) diff --git a/api/v1alpha1/loadbalancer_types.go b/api/v1alpha1/loadbalancer_types.go index 8e0dab5086..1bcf57de67 100644 --- a/api/v1alpha1/loadbalancer_types.go +++ b/api/v1alpha1/loadbalancer_types.go @@ -13,6 +13,7 @@ import gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" // +kubebuilder:validation:XValidation:rule="self.type == 'ConsistentHash' ? has(self.consistentHash) : !has(self.consistentHash)",message="If LoadBalancer type is consistentHash, consistentHash field needs to be set." // +kubebuilder:validation:XValidation:rule="self.type in ['Random', 'ConsistentHash'] ? !has(self.slowStart) : true ",message="Currently SlowStart is only supported for RoundRobin and LeastRequest load balancers." // +kubebuilder:validation:XValidation:rule="self.type == 'ConsistentHash' ? !has(self.zoneAware) : true ",message="Currently ZoneAware is only supported for LeastRequest, Random, and RoundRobin load balancers." +// +kubebuilder:validation:XValidation:rule="has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && has(self.zoneAware.weightedZones)) : true",message="ZoneAware PreferLocal and WeightedZones cannot be specified together." type LoadBalancer struct { // Type decides the type of Load Balancer policy. // Valid LoadBalancerType values are @@ -184,6 +185,13 @@ type ZoneAware struct { // // +optional PreferLocal *PreferLocalZone `json:"preferLocal,omitempty"` + + // WeightedZones configures weight-based traffic distribution across locality zones. + // Traffic is distributed proportionally based on the sum of all zone weights. + // + // +optional + // +notImplementedHide + WeightedZones []WeightedZoneConfig `json:"weightedZones,omitempty"` } // PreferLocalZone configures zone-aware routing to prefer sending traffic to the local locality zone. @@ -217,6 +225,18 @@ type ForceLocalZone struct { MinEndpointsInZoneThreshold *uint32 `json:"minEndpointsInZoneThreshold,omitempty"` } +// WeightedZoneConfig defines the weight for a specific locality zone. +type WeightedZoneConfig struct { + // Zone specifies the zone this weight applies to. + // Empty string means apply to all zones within the region. + Zone string `json:"zone,omitempty"` + + // Weight defines the weight for this locality. + // Higher values receive more traffic. The actual traffic distribution + // is proportional to this value relative to other localities. + Weight uint32 `json:"weight"` +} + // EndpointOverride defines the configuration for endpoint override. // This allows endpoint picking to be implemented based on request headers or metadata. // It extracts selected override endpoints from the specified sources (request headers, metadata, etc.). diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index fb1eedf645..40facc460f 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -15,9 +15,11 @@ import ( corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" + runtime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/gateway-api/apis/v1alpha3" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -162,11 +164,6 @@ func (in *ActiveHealthCheck) DeepCopyInto(out *ActiveHealthCheck) { *out = new(GRPCActiveHealthChecker) (*in).DeepCopyInto(*out) } - if in.Overrides != nil { - in, out := &in.Overrides, &out.Overrides - *out = new(HealthCheckOverrides) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveHealthCheck. @@ -374,11 +371,6 @@ func (in *BackendConnection) DeepCopyInto(out *BackendConnection) { x := (*in).DeepCopy() *out = &x } - if in.Preconnect != nil { - in, out := &in.Preconnect, &out.Preconnect - *out = new(PreconnectPolicy) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendConnection. @@ -463,35 +455,10 @@ func (in *BackendList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BackendMetrics) DeepCopyInto(out *BackendMetrics) { - *out = *in - if in.RouteStatName != nil { - in, out := &in.RouteStatName, &out.RouteStatName - *out = new(string) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendMetrics. -func (in *BackendMetrics) DeepCopy() *BackendMetrics { - if in == nil { - return nil - } - out := new(BackendMetrics) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendRef) DeepCopyInto(out *BackendRef) { *out = *in in.BackendObjectReference.DeepCopyInto(&out.BackendObjectReference) - if in.Weight != nil { - in, out := &in.Weight, &out.Weight - *out = new(uint32) - **out = **in - } if in.Fallback != nil { in, out := &in.Fallback, &out.Fallback *out = new(bool) @@ -604,7 +571,7 @@ func (in *BackendTLSSettings) DeepCopyInto(out *BackendTLSSettings) { } if in.WellKnownCACertificates != nil { in, out := &in.WellKnownCACertificates, &out.WellKnownCACertificates - *out = new(v1.WellKnownCACertificatesType) + *out = new(v1alpha3.WellKnownCACertificatesType) **out = **in } if in.InsecureSkipVerify != nil { @@ -617,11 +584,6 @@ func (in *BackendTLSSettings) DeepCopyInto(out *BackendTLSSettings) { *out = new(v1.PreciseHostname) **out = **in } - if in.BackendTLSConfig != nil { - in, out := &in.BackendTLSConfig, &out.BackendTLSConfig - *out = new(BackendTLSConfig) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSSettings. @@ -642,11 +604,6 @@ func (in *BackendTelemetry) DeepCopyInto(out *BackendTelemetry) { *out = new(Tracing) (*in).DeepCopyInto(*out) } - if in.Metrics != nil { - in, out := &in.Metrics, &out.Metrics - *out = new(BackendMetrics) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTelemetry. @@ -754,17 +711,6 @@ func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec) } } } - if in.Compressor != nil { - in, out := &in.Compressor, &out.Compressor - *out = make([]*Compression, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(Compression) - (*in).DeepCopyInto(*out) - } - } - } if in.ResponseOverride != nil { in, out := &in.ResponseOverride, &out.ResponseOverride *out = make([]*ResponseOverride, len(*in)) @@ -797,11 +743,6 @@ func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec) *out = new(BackendTelemetry) (*in).DeepCopyInto(*out) } - if in.RoutingType != nil { - in, out := &in.RoutingType, &out.RoutingType - *out = new(RoutingType) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTrafficPolicySpec. @@ -1209,11 +1150,6 @@ func (in *ClientTrafficPolicySpec) DeepCopyInto(out *ClientTrafficPolicySpec) { *out = new(HealthCheckSettings) **out = **in } - if in.Scheme != nil { - in, out := &in.Scheme, &out.Scheme - *out = new(SchemeHeaderTransform) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientTrafficPolicySpec. @@ -1366,16 +1302,6 @@ func (in *Compression) DeepCopyInto(out *Compression) { *out = new(GzipCompressor) **out = **in } - if in.Zstd != nil { - in, out := &in.Zstd, &out.Zstd - *out = new(ZstdCompressor) - **out = **in - } - if in.MinContentLength != nil { - in, out := &in.MinContentLength, &out.MinContentLength - x := (*in).DeepCopy() - *out = &x - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Compression. @@ -1451,33 +1377,11 @@ func (in *ConsistentHash) DeepCopyInto(out *ConsistentHash) { *out = new(Header) **out = **in } - if in.Headers != nil { - in, out := &in.Headers, &out.Headers - *out = make([]*Header, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(Header) - **out = **in - } - } - } if in.Cookie != nil { in, out := &in.Cookie, &out.Cookie *out = new(Cookie) (*in).DeepCopyInto(*out) } - if in.QueryParams != nil { - in, out := &in.QueryParams, &out.QueryParams - *out = make([]*QueryParam, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(QueryParam) - **out = **in - } - } - } if in.TableSize != nil { in, out := &in.TableSize, &out.TableSize *out = new(uint64) @@ -1495,31 +1399,6 @@ func (in *ConsistentHash) DeepCopy() *ConsistentHash { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ContextExtension) DeepCopyInto(out *ContextExtension) { - *out = *in - if in.Value != nil { - in, out := &in.Value, &out.Value - *out = new(string) - **out = **in - } - if in.ValueRef != nil { - in, out := &in.ValueRef, &out.ValueRef - *out = new(LocalObjectKeyReference) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContextExtension. -func (in *ContextExtension) DeepCopy() *ContextExtension { - if in == nil { - return nil - } - out := new(ContextExtension) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Cookie) DeepCopyInto(out *Cookie) { *out = *in @@ -2043,26 +1922,6 @@ func (in *EnvoyGatewayFileResourceProvider) DeepCopy() *EnvoyGatewayFileResource // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EnvoyGatewayHostInfrastructureProvider) DeepCopyInto(out *EnvoyGatewayHostInfrastructureProvider) { *out = *in - if in.ConfigHome != nil { - in, out := &in.ConfigHome, &out.ConfigHome - *out = new(string) - **out = **in - } - if in.DataHome != nil { - in, out := &in.DataHome, &out.DataHome - *out = new(string) - **out = **in - } - if in.StateHome != nil { - in, out := &in.StateHome, &out.StateHome - *out = new(string) - **out = **in - } - if in.RuntimeDir != nil { - in, out := &in.RuntimeDir, &out.RuntimeDir - *out = new(string) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyGatewayHostInfrastructureProvider. @@ -2081,7 +1940,7 @@ func (in *EnvoyGatewayInfrastructureProvider) DeepCopyInto(out *EnvoyGatewayInfr if in.Host != nil { in, out := &in.Host, &out.Host *out = new(EnvoyGatewayHostInfrastructureProvider) - (*in).DeepCopyInto(*out) + **out = **in } } @@ -2108,11 +1967,6 @@ func (in *EnvoyGatewayKubernetesProvider) DeepCopyInto(out *EnvoyGatewayKubernet *out = new(KubernetesHorizontalPodAutoscalerSpec) (*in).DeepCopyInto(*out) } - if in.RateLimitPDB != nil { - in, out := &in.RateLimitPDB, &out.RateLimitPDB - *out = new(KubernetesPodDisruptionBudgetSpec) - (*in).DeepCopyInto(*out) - } if in.Watch != nil { in, out := &in.Watch, &out.Watch *out = new(KubernetesWatchMode) @@ -2170,11 +2024,6 @@ func (in *EnvoyGatewayLogging) DeepCopyInto(out *EnvoyGatewayLogging) { (*out)[key] = val } } - if in.Encoder != nil { - in, out := &in.Encoder, &out.Encoder - *out = new(EnvoyGatewayLogEncoder) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyGatewayLogging. @@ -2347,11 +2196,6 @@ func (in *EnvoyGatewaySpec) DeepCopyInto(out *EnvoyGatewaySpec) { *out = new(EnvoyGatewayTelemetry) (*in).DeepCopyInto(*out) } - if in.XDSServer != nil { - in, out := &in.XDSServer, &out.XDSServer - *out = new(XDSServer) - (*in).DeepCopyInto(*out) - } if in.RateLimit != nil { in, out := &in.RateLimit, &out.RateLimit *out = new(RateLimit) @@ -2367,21 +2211,11 @@ func (in *EnvoyGatewaySpec) DeepCopyInto(out *EnvoyGatewaySpec) { *out = new(ExtensionAPISettings) **out = **in } - if in.GatewayAPI != nil { - in, out := &in.GatewayAPI, &out.GatewayAPI - *out = new(GatewayAPISettings) - (*in).DeepCopyInto(*out) - } if in.RuntimeFlags != nil { in, out := &in.RuntimeFlags, &out.RuntimeFlags *out = new(RuntimeFlags) (*in).DeepCopyInto(*out) } - if in.EnvoyProxy != nil { - in, out := &in.EnvoyProxy, &out.EnvoyProxy - *out = new(EnvoyProxySpec) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyGatewaySpec. @@ -2519,7 +2353,7 @@ func (in *EnvoyPatchPolicySpec) DeepCopyInto(out *EnvoyPatchPolicySpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - out.TargetRef = in.TargetRef + in.TargetRef.DeepCopyInto(&out.TargetRef) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyPatchPolicySpec. @@ -2538,7 +2372,7 @@ func (in *EnvoyProxy) DeepCopyInto(out *EnvoyProxy) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) + out.Status = in.Status } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyProxy. @@ -2559,29 +2393,6 @@ func (in *EnvoyProxy) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *EnvoyProxyAncestorStatus) DeepCopyInto(out *EnvoyProxyAncestorStatus) { - *out = *in - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - in.AncestorRef.DeepCopyInto(&out.AncestorRef) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyProxyAncestorStatus. -func (in *EnvoyProxyAncestorStatus) DeepCopy() *EnvoyProxyAncestorStatus { - if in == nil { - return nil - } - out := new(EnvoyProxyAncestorStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EnvoyProxyHostProvider) DeepCopyInto(out *EnvoyProxyHostProvider) { *out = *in @@ -2795,13 +2606,6 @@ func (in *EnvoyProxySpec) DeepCopy() *EnvoyProxySpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EnvoyProxyStatus) DeepCopyInto(out *EnvoyProxyStatus) { *out = *in - if in.Ancestors != nil { - in, out := &in.Ancestors, &out.Ancestors - *out = make([]EnvoyProxyAncestorStatus, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyProxyStatus. @@ -2852,17 +2656,6 @@ func (in *ExtAuth) DeepCopyInto(out *ExtAuth) { *out = new(bool) **out = **in } - if in.ContextExtensions != nil { - in, out := &in.ContextExtensions, &out.ContextExtensions - *out = make([]*ContextExtension, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(ContextExtension) - (*in).DeepCopyInto(*out) - } - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtAuth. @@ -3364,26 +3157,6 @@ func (in *Gateway) DeepCopy() *Gateway { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayAPISettings) DeepCopyInto(out *GatewayAPISettings) { - *out = *in - if in.Enabled != nil { - in, out := &in.Enabled, &out.Enabled - *out = make([]GatewayAPI, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayAPISettings. -func (in *GatewayAPISettings) DeepCopy() *GatewayAPISettings { - if in == nil { - return nil - } - out := new(GatewayAPISettings) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GlobalRateLimit) DeepCopyInto(out *GlobalRateLimit) { *out = *in @@ -3606,26 +3379,6 @@ func (in *HTTPClientTimeout) DeepCopy() *HTTPClientTimeout { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPCookieMatch) DeepCopyInto(out *HTTPCookieMatch) { - *out = *in - if in.Type != nil { - in, out := &in.Type, &out.Type - *out = new(CookieMatchType) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPCookieMatch. -func (in *HTTPCookieMatch) DeepCopy() *HTTPCookieMatch { - if in == nil { - return nil - } - out := new(HTTPCookieMatch) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPCredentialInjectionFilter) DeepCopyInto(out *HTTPCredentialInjectionFilter) { *out = *in @@ -3726,23 +3479,11 @@ func (in *HTTPHeaderFilter) DeepCopyInto(out *HTTPHeaderFilter) { *out = make([]v1.HTTPHeader, len(*in)) copy(*out, *in) } - if in.AddIfAbsent != nil { - in, out := &in.AddIfAbsent, &out.AddIfAbsent - *out = make([]v1.HTTPHeader, len(*in)) - copy(*out, *in) - } if in.Remove != nil { in, out := &in.Remove, &out.Remove *out = make([]string, len(*in)) copy(*out, *in) } - if in.RemoveOnMatch != nil { - in, out := &in.RemoveOnMatch, &out.RemoveOnMatch - *out = make([]StringMatch, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeaderFilter. @@ -3871,13 +3612,6 @@ func (in *HTTPRouteFilterSpec) DeepCopyInto(out *HTTPRouteFilterSpec) { *out = new(HTTPCredentialInjectionFilter) (*in).DeepCopyInto(*out) } - if in.Matches != nil { - in, out := &in.Matches, &out.Matches - *out = make([]HTTPRouteMatchFilter, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteFilterSpec. @@ -3890,28 +3624,6 @@ func (in *HTTPRouteFilterSpec) DeepCopy() *HTTPRouteFilterSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPRouteMatchFilter) DeepCopyInto(out *HTTPRouteMatchFilter) { - *out = *in - if in.Cookies != nil { - in, out := &in.Cookies, &out.Cookies - *out = make([]HTTPCookieMatch, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteMatchFilter. -func (in *HTTPRouteMatchFilter) DeepCopy() *HTTPRouteMatchFilter { - if in == nil { - return nil - } - out := new(HTTPRouteMatchFilter) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPTimeout) DeepCopyInto(out *HTTPTimeout) { *out = *in @@ -3930,11 +3642,6 @@ func (in *HTTPTimeout) DeepCopyInto(out *HTTPTimeout) { *out = new(v1.Duration) **out = **in } - if in.MaxStreamDuration != nil { - in, out := &in.MaxStreamDuration, &out.MaxStreamDuration - *out = new(v1.Duration) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPTimeout. @@ -4127,21 +3834,6 @@ func (in *HealthCheck) DeepCopy() *HealthCheck { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HealthCheckOverrides) DeepCopyInto(out *HealthCheckOverrides) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthCheckOverrides. -func (in *HealthCheckOverrides) DeepCopy() *HealthCheckOverrides { - if in == nil { - return nil - } - out := new(HealthCheckOverrides) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HealthCheckSettings) DeepCopyInto(out *HealthCheckSettings) { *out = *in @@ -4798,11 +4490,6 @@ func (in *KubernetesPodSpec) DeepCopyInto(out *KubernetesPodSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.PriorityClassName != nil { - in, out := &in.PriorityClassName, &out.PriorityClassName - *out = new(string) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesPodSpec. @@ -5064,22 +4751,6 @@ func (in *LocalJWKS) DeepCopy() *LocalJWKS { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *LocalObjectKeyReference) DeepCopyInto(out *LocalObjectKeyReference) { - *out = *in - out.LocalObjectReference = in.LocalObjectReference -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalObjectKeyReference. -func (in *LocalObjectKeyReference) DeepCopy() *LocalObjectKeyReference { - if in == nil { - return nil - } - out := new(LocalObjectKeyReference) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LocalRateLimit) DeepCopyInto(out *LocalRateLimit) { *out = *in @@ -5127,26 +4798,6 @@ func (in *Lua) DeepCopy() *Lua { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MethodMatch) DeepCopyInto(out *MethodMatch) { - *out = *in - if in.Invert != nil { - in, out := &in.Invert, &out.Invert - *out = new(bool) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MethodMatch. -func (in *MethodMatch) DeepCopy() *MethodMatch { - if in == nil { - return nil - } - out := new(MethodMatch) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OIDC) DeepCopyInto(out *OIDC) { *out = *in @@ -5379,18 +5030,6 @@ func (in *OpenTelemetryEnvoyProxyAccessLog) DeepCopyInto(out *OpenTelemetryEnvoy (*out)[key] = val } } - if in.ResourceAttributes != nil { - in, out := &in.ResourceAttributes, &out.ResourceAttributes - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Headers != nil { - in, out := &in.Headers, &out.Headers - *out = make([]v1.HTTPHeader, len(*in)) - copy(*out, *in) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenTelemetryEnvoyProxyAccessLog. @@ -5403,33 +5042,6 @@ func (in *OpenTelemetryEnvoyProxyAccessLog) DeepCopy() *OpenTelemetryEnvoyProxyA return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *OpenTelemetryTracingProvider) DeepCopyInto(out *OpenTelemetryTracingProvider) { - *out = *in - if in.Headers != nil { - in, out := &in.Headers, &out.Headers - *out = make([]v1.HTTPHeader, len(*in)) - copy(*out, *in) - } - if in.ResourceAttributes != nil { - in, out := &in.ResourceAttributes, &out.ResourceAttributes - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenTelemetryTracingProvider. -func (in *OpenTelemetryTracingProvider) DeepCopy() *OpenTelemetryTracingProvider { - if in == nil { - return nil - } - out := new(OpenTelemetryTracingProvider) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Operation) DeepCopyInto(out *Operation) { *out = *in @@ -5504,11 +5116,6 @@ func (in *PassiveHealthCheck) DeepCopyInto(out *PassiveHealthCheck) { *out = new(int32) **out = **in } - if in.FailurePercentageThreshold != nil { - in, out := &in.FailurePercentageThreshold, &out.FailurePercentageThreshold - *out = new(uint32) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PassiveHealthCheck. @@ -5521,31 +5128,6 @@ func (in *PassiveHealthCheck) DeepCopy() *PassiveHealthCheck { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PathMatch) DeepCopyInto(out *PathMatch) { - *out = *in - if in.Type != nil { - in, out := &in.Type, &out.Type - *out = new(v1.PathMatchType) - **out = **in - } - if in.Invert != nil { - in, out := &in.Invert, &out.Invert - *out = new(bool) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PathMatch. -func (in *PathMatch) DeepCopy() *PathMatch { - if in == nil { - return nil - } - out := new(PathMatch) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PathSettings) DeepCopyInto(out *PathSettings) { *out = *in @@ -5621,12 +5203,12 @@ func (in *PolicyTargetReferences) DeepCopyInto(out *PolicyTargetReferences) { *out = *in if in.TargetRef != nil { in, out := &in.TargetRef, &out.TargetRef - *out = new(v1.LocalPolicyTargetReferenceWithSectionName) + *out = new(v1alpha2.LocalPolicyTargetReferenceWithSectionName) (*in).DeepCopyInto(*out) } if in.TargetRefs != nil { in, out := &in.TargetRefs, &out.TargetRefs - *out = make([]v1.LocalPolicyTargetReferenceWithSectionName, len(*in)) + *out = make([]v1alpha2.LocalPolicyTargetReferenceWithSectionName, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -5650,31 +5232,6 @@ func (in *PolicyTargetReferences) DeepCopy() *PolicyTargetReferences { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PreconnectPolicy) DeepCopyInto(out *PreconnectPolicy) { - *out = *in - if in.PerEndpointPercent != nil { - in, out := &in.PerEndpointPercent, &out.PerEndpointPercent - *out = new(uint32) - **out = **in - } - if in.PredictivePercent != nil { - in, out := &in.PredictivePercent, &out.PredictivePercent - *out = new(uint32) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreconnectPolicy. -func (in *PreconnectPolicy) DeepCopy() *PreconnectPolicy { - if in == nil { - return nil - } - out := new(PreconnectPolicy) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PreferLocalZone) DeepCopyInto(out *PreferLocalZone) { *out = *in @@ -5725,11 +5282,6 @@ func (in *Principal) DeepCopyInto(out *Principal) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.SourceCIDRs != nil { - in, out := &in.SourceCIDRs, &out.SourceCIDRs - *out = make([]CIDR, len(*in)) - copy(*out, *in) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Principal. @@ -5817,11 +5369,6 @@ func (in *ProxyAccessLog) DeepCopy() *ProxyAccessLog { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProxyAccessLogFormat) DeepCopyInto(out *ProxyAccessLogFormat) { *out = *in - if in.Type != nil { - in, out := &in.Type, &out.Type - *out = new(ProxyAccessLogFormatType) - **out = **in - } if in.Text != nil { in, out := &in.Text, &out.Text *out = new(string) @@ -6050,28 +5597,6 @@ func (in *ProxyOpenTelemetrySink) DeepCopyInto(out *ProxyOpenTelemetrySink) { *out = new(string) **out = **in } - if in.ReportCountersAsDeltas != nil { - in, out := &in.ReportCountersAsDeltas, &out.ReportCountersAsDeltas - *out = new(bool) - **out = **in - } - if in.ReportHistogramsAsDeltas != nil { - in, out := &in.ReportHistogramsAsDeltas, &out.ReportHistogramsAsDeltas - *out = new(bool) - **out = **in - } - if in.Headers != nil { - in, out := &in.Headers, &out.Headers - *out = make([]v1.HTTPHeader, len(*in)) - copy(*out, *in) - } - if in.ResourceAttributes != nil { - in, out := &in.ResourceAttributes, &out.ResourceAttributes - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyOpenTelemetrySink. @@ -6157,11 +5682,6 @@ func (in *ProxyTelemetry) DeepCopyInto(out *ProxyTelemetry) { *out = new(ProxyMetrics) (*in).DeepCopyInto(*out) } - if in.RequestID != nil { - in, out := &in.RequestID, &out.RequestID - *out = new(RequestIDSettings) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyTelemetry. @@ -6177,12 +5697,23 @@ func (in *ProxyTelemetry) DeepCopy() *ProxyTelemetry { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProxyTracing) DeepCopyInto(out *ProxyTracing) { *out = *in - in.Tracing.DeepCopyInto(&out.Tracing) if in.SamplingRate != nil { in, out := &in.SamplingRate, &out.SamplingRate *out = new(uint32) **out = **in } + if in.SamplingFraction != nil { + in, out := &in.SamplingFraction, &out.SamplingFraction + *out = new(v1.Fraction) + (*in).DeepCopyInto(*out) + } + if in.CustomTags != nil { + in, out := &in.CustomTags, &out.CustomTags + *out = make(map[string]CustomTag, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } in.Provider.DeepCopyInto(&out.Provider) } @@ -6196,51 +5727,6 @@ func (in *ProxyTracing) DeepCopy() *ProxyTracing { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *QueryParam) DeepCopyInto(out *QueryParam) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QueryParam. -func (in *QueryParam) DeepCopy() *QueryParam { - if in == nil { - return nil - } - out := new(QueryParam) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *QueryParamMatch) DeepCopyInto(out *QueryParamMatch) { - *out = *in - if in.Type != nil { - in, out := &in.Type, &out.Type - *out = new(QueryParamMatchType) - **out = **in - } - if in.Value != nil { - in, out := &in.Value, &out.Value - *out = new(string) - **out = **in - } - if in.Invert != nil { - in, out := &in.Invert, &out.Invert - *out = new(bool) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QueryParamMatch. -func (in *QueryParamMatch) DeepCopy() *QueryParamMatch { - if in == nil { - return nil - } - out := new(QueryParamMatch) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RateLimit) DeepCopyInto(out *RateLimit) { *out = *in @@ -6428,11 +5914,6 @@ func (in *RateLimitRule) DeepCopyInto(out *RateLimitRule) { *out = new(bool) **out = **in } - if in.ShadowMode != nil { - in, out := &in.ShadowMode, &out.ShadowMode - *out = new(bool) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitRule. @@ -6455,30 +5936,11 @@ func (in *RateLimitSelectCondition) DeepCopyInto(out *RateLimitSelectCondition) (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.Methods != nil { - in, out := &in.Methods, &out.Methods - *out = make([]MethodMatch, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Path != nil { - in, out := &in.Path, &out.Path - *out = new(PathMatch) - (*in).DeepCopyInto(*out) - } if in.SourceCIDR != nil { in, out := &in.SourceCIDR, &out.SourceCIDR *out = new(SourceMatch) (*in).DeepCopyInto(*out) } - if in.QueryParams != nil { - in, out := &in.QueryParams, &out.QueryParams - *out = make([]QueryParamMatch, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitSelectCondition. @@ -6494,11 +5956,6 @@ func (in *RateLimitSelectCondition) DeepCopy() *RateLimitSelectCondition { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RateLimitSpec) DeepCopyInto(out *RateLimitSpec) { *out = *in - if in.Type != nil { - in, out := &in.Type, &out.Type - *out = new(RateLimitType) - **out = **in - } if in.Global != nil { in, out := &in.Global, &out.Global *out = new(GlobalRateLimit) @@ -6698,26 +6155,6 @@ func (in *RequestHeaderCustomTag) DeepCopy() *RequestHeaderCustomTag { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RequestIDSettings) DeepCopyInto(out *RequestIDSettings) { - *out = *in - if in.Tracing != nil { - in, out := &in.Tracing, &out.Tracing - *out = new(RequestIDExtensionAction) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestIDSettings. -func (in *RequestIDSettings) DeepCopy() *RequestIDSettings { - if in == nil { - return nil - } - out := new(RequestIDSettings) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResponseOverride) DeepCopyInto(out *ResponseOverride) { *out = *in @@ -7468,18 +6905,6 @@ func (in *Tracing) DeepCopyInto(out *Tracing) { (*out)[key] = *val.DeepCopy() } } - if in.Tags != nil { - in, out := &in.Tags, &out.Tags - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.SpanName != nil { - in, out := &in.SpanName, &out.SpanName - *out = new(TracingSpanName) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Tracing. @@ -7511,11 +6936,6 @@ func (in *TracingProvider) DeepCopyInto(out *TracingProvider) { *out = new(ZipkinTracingProvider) (*in).DeepCopyInto(*out) } - if in.OpenTelemetry != nil { - in, out := &in.OpenTelemetry, &out.OpenTelemetry - *out = new(OpenTelemetryTracingProvider) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TracingProvider. @@ -7528,21 +6948,6 @@ func (in *TracingProvider) DeepCopy() *TracingProvider { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TracingSpanName) DeepCopyInto(out *TracingSpanName) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TracingSpanName. -func (in *TracingSpanName) DeepCopy() *TracingSpanName { - if in == nil { - return nil - } - out := new(TracingSpanName) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TranslationConfig) DeepCopyInto(out *TranslationConfig) { *out = *in @@ -7701,26 +7106,16 @@ func (in *WasmEnv) DeepCopy() *WasmEnv { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *XDSServer) DeepCopyInto(out *XDSServer) { +func (in *WeightedZoneConfig) DeepCopyInto(out *WeightedZoneConfig) { *out = *in - if in.MaxConnectionAge != nil { - in, out := &in.MaxConnectionAge, &out.MaxConnectionAge - *out = new(v1.Duration) - **out = **in - } - if in.MaxConnectionAgeGrace != nil { - in, out := &in.MaxConnectionAgeGrace, &out.MaxConnectionAgeGrace - *out = new(v1.Duration) - **out = **in - } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new XDSServer. -func (in *XDSServer) DeepCopy() *XDSServer { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WeightedZoneConfig. +func (in *WeightedZoneConfig) DeepCopy() *WeightedZoneConfig { if in == nil { return nil } - out := new(XDSServer) + out := new(WeightedZoneConfig) in.DeepCopyInto(out) return out } @@ -7838,6 +7233,11 @@ func (in *ZoneAware) DeepCopyInto(out *ZoneAware) { *out = new(PreferLocalZone) (*in).DeepCopyInto(*out) } + if in.WeightedZones != nil { + in, out := &in.WeightedZones, &out.WeightedZones + *out = make([]WeightedZoneConfig, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZoneAware. @@ -7849,18 +7249,3 @@ func (in *ZoneAware) DeepCopy() *ZoneAware { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ZstdCompressor) DeepCopyInto(out *ZstdCompressor) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZstdCompressor. -func (in *ZstdCompressor) DeepCopy() *ZstdCompressor { - if in == nil { - return nil - } - out := new(ZstdCompressor) - in.DeepCopyInto(out) - return out -} diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index 93d46242e4..c402415c4c 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -931,6 +931,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight for a + specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -948,6 +972,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot be specified + together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && + has(self.zoneAware.weightedZones)) : true' mergeType: description: |- MergeType determines how this configuration is merged with existing BackendTrafficPolicy diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 996d26a91c..b710de7681 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -969,6 +969,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight + for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -986,6 +1010,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml index f905780b1c..2e0fb3323d 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -12063,6 +12063,31 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -12082,6 +12107,11 @@ spec: and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -13332,6 +13362,31 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -13351,6 +13406,11 @@ spec: and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -14749,6 +14809,31 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality + zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -14767,6 +14852,11 @@ spec: load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : + true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -16086,6 +16176,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -16103,6 +16217,10 @@ spec: LeastRequest, Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml index 3bfde648f7..7028a91c93 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1593,6 +1593,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -1610,6 +1634,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -2750,6 +2778,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -2767,6 +2819,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -4122,6 +4178,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -4140,6 +4220,10 @@ spec: balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -5544,6 +5628,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -5561,6 +5669,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index 795271b526..dec272f233 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -930,6 +930,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight for a + specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -947,6 +971,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot be specified + together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && + has(self.zoneAware.weightedZones)) : true' mergeType: description: |- MergeType determines how this configuration is merged with existing BackendTrafficPolicy diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 97aeacf69e..49e0303c36 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -968,6 +968,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight + for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -985,6 +1009,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml index 900b4e5fa0..118c4c3380 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -12062,6 +12062,31 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -12081,6 +12106,11 @@ spec: and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -13331,6 +13361,31 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -13350,6 +13405,11 @@ spec: and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -14748,6 +14808,31 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality + zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -14766,6 +14851,11 @@ spec: load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : + true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -16085,6 +16175,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -16102,6 +16216,10 @@ spec: LeastRequest, Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index 8303f1b640..4381145a84 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1592,6 +1592,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -1609,6 +1633,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -2749,6 +2777,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -2766,6 +2818,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -4121,6 +4177,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -4139,6 +4219,10 @@ spec: balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -5543,6 +5627,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -5560,6 +5668,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index b4e5822d70..5ce6b2f2ac 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -5719,6 +5719,21 @@ _Appears in:_ | `hostKeys` | _string array_ | false | | HostKeys is a list of keys for environment variables from the host envoy process
that should be passed into the Wasm VM. This is useful for passing secrets to to Wasm extensions. | +#### WeightedZoneConfig + + + +WeightedZoneConfig defines the weight for a specific locality zone. + +_Appears in:_ +- [ZoneAware](#zoneaware) + +| Field | Type | Required | Default | Description | +| --- | --- | --- | --- | --- | +| `zone` | _string_ | true | | Zone specifies the zone this weight applies to.
Empty string means apply to all zones within the region. | +| `weight` | _integer_ | true | | Weight defines the weight for this locality.
Higher values receive more traffic. The actual traffic distribution
is proportional to this value relative to other localities. | + + #### WithUnderscoresAction _Underlying type:_ _string_ diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml index 8ad08a02bb..8c0a6aeae9 100644 --- a/test/helm/gateway-crds-helm/all.out.yaml +++ b/test/helm/gateway-crds-helm/all.out.yaml @@ -22230,6 +22230,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight for a + specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -22247,6 +22271,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot be specified + together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && + has(self.zoneAware.weightedZones)) : true' mergeType: description: |- MergeType determines how this configuration is merged with existing BackendTrafficPolicy @@ -27176,6 +27204,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight + for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -27193,6 +27245,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -40966,6 +41022,31 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -40985,6 +41066,11 @@ spec: and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -42235,6 +42321,31 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -42254,6 +42365,11 @@ spec: and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -43652,6 +43768,31 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality + zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -43670,6 +43811,11 @@ spec: load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : + true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -44989,6 +45135,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -45006,6 +45176,10 @@ spec: LeastRequest, Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -47668,6 +47842,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -47685,6 +47883,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -48825,6 +49027,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -48842,6 +49068,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -50197,6 +50427,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -50215,6 +50469,10 @@ spec: balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -51619,6 +51877,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -51636,6 +51918,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml index ebb016d68c..60b82af41a 100644 --- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml +++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml @@ -1410,6 +1410,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight for a + specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -1427,6 +1451,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot be specified + together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && + has(self.zoneAware.weightedZones)) : true' mergeType: description: |- MergeType determines how this configuration is merged with existing BackendTrafficPolicy @@ -6356,6 +6384,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the weight + for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -6373,6 +6425,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -20146,6 +20202,31 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -20165,6 +20246,11 @@ spec: and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -21415,6 +21501,31 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig + defines the weight for a specific + locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -21434,6 +21545,11 @@ spec: and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) + : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with @@ -22832,6 +22948,31 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality + zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -22850,6 +22991,11 @@ spec: load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : + true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -24169,6 +24315,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -24186,6 +24356,10 @@ spec: LeastRequest, Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -26848,6 +27022,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -26865,6 +27063,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -28005,6 +28207,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -28022,6 +28248,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -29377,6 +29607,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines + the weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -29395,6 +29649,10 @@ spec: balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones + cannot be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. @@ -30799,6 +31057,30 @@ spec: minimum: 0 type: integer type: object + weightedZones: + description: |- + WeightedZones configures weight-based traffic distribution across locality zones. + Traffic is distributed proportionally based on the sum of all zone weights. + items: + description: WeightedZoneConfig defines the + weight for a specific locality zone. + properties: + weight: + description: |- + Weight defines the weight for this locality. + Higher values receive more traffic. The actual traffic distribution + is proportional to this value relative to other localities. + format: int32 + type: integer + zone: + description: |- + Zone specifies the zone this weight applies to. + Empty string means apply to all zones within the region. + type: string + required: + - weight + type: object + type: array type: object required: - type @@ -30816,6 +31098,10 @@ spec: Random, and RoundRobin load balancers. rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : true ' + - message: ZoneAware PreferLocal and WeightedZones cannot + be specified together. + rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) + && has(self.zoneAware.weightedZones)) : true' proxyProtocol: description: ProxyProtocol enables the Proxy Protocol when communicating with the backend. From dde63267a943754a2a84096566eb23f6ae161ba4 Mon Sep 17 00:00:00 2001 From: jukie <10012479+jukie@users.noreply.github.com> Date: Wed, 15 Oct 2025 20:00:42 -0600 Subject: [PATCH 02/13] cel-test Signed-off-by: jukie <10012479+jukie@users.noreply.github.com> --- .../backendtrafficpolicy_test.go | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index 741affc1ca..949677c2c9 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -422,6 +422,37 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, wantErrors: []string{}, }, + { + desc: "leastRequest with ZoneAware PreferLocal and WeightedZones set", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + }, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.LeastRequestLoadBalancerType, + ZoneAware: &egv1a1.ZoneAware{ + PreferLocal: &egv1a1.PreferLocalZone{}, + WeightedZones: []egv1a1.WeightedZoneConfig{{ + Zone: "zone1", + Weight: uint32(10), + }}, + }, + }, + }, + } + }, + wantErrors: []string{ + "spec.loadBalancer: Invalid value: \"object\": ZoneAware PreferLocal and WeightedZones cannot be specified together", + }, + }, { desc: "leastRequest with SlowStar is set", mutate: func(btp *egv1a1.BackendTrafficPolicy) { From e8e5a044a0994fbca3c7b15b3cba978dcf606205 Mon Sep 17 00:00:00 2001 From: jukie <10012479+jukie@users.noreply.github.com> Date: Mon, 20 Oct 2025 15:42:59 -0600 Subject: [PATCH 03/13] fix cel Signed-off-by: jukie <10012479+jukie@users.noreply.github.com> --- test/cel-validation/backendtrafficpolicy_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index 949677c2c9..858c21d447 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -427,11 +427,11 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { mutate: func(btp *egv1a1.BackendTrafficPolicy) { btp.Spec = egv1a1.BackendTrafficPolicySpec{ PolicyTargetReferences: egv1a1.PolicyTargetReferences{ - TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{ - LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{ - Group: gwapiv1a2.Group("gateway.networking.k8s.io"), - Kind: gwapiv1a2.Kind("Gateway"), - Name: gwapiv1a2.ObjectName("eg"), + TargetRef: &gwapiv1.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1.LocalPolicyTargetReference{ + Group: gwapiv1.Group("gateway.networking.k8s.io"), + Kind: gwapiv1.Kind("Gateway"), + Name: gwapiv1.ObjectName("eg"), }, }, }, From fd7820101682025a26fa699911620c05202e997b Mon Sep 17 00:00:00 2001 From: jukie <10012479+jukie@users.noreply.github.com> Date: Tue, 18 Nov 2025 18:49:12 -0700 Subject: [PATCH 04/13] regen Signed-off-by: jukie <10012479+jukie@users.noreply.github.com> --- api/v1alpha1/zz_generated.deepcopy.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 40facc460f..429e100fc8 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -7120,6 +7120,31 @@ func (in *WeightedZoneConfig) DeepCopy() *WeightedZoneConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *XDSServer) DeepCopyInto(out *XDSServer) { + *out = *in + if in.MaxConnectionAge != nil { + in, out := &in.MaxConnectionAge, &out.MaxConnectionAge + *out = new(v1.Duration) + **out = **in + } + if in.MaxConnectionAgeGrace != nil { + in, out := &in.MaxConnectionAgeGrace, &out.MaxConnectionAgeGrace + *out = new(v1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new XDSServer. +func (in *XDSServer) DeepCopy() *XDSServer { + if in == nil { + return nil + } + out := new(XDSServer) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *XDSTranslatorHooks) DeepCopyInto(out *XDSTranslatorHooks) { *out = *in From 6fc119f297401a3dc78d65bfe2a6916934913f85 Mon Sep 17 00:00:00 2001 From: jukie <10012479+Jukie@users.noreply.github.com> Date: Thu, 5 Feb 2026 23:10:38 -0700 Subject: [PATCH 05/13] implementation Signed-off-by: jukie <10012479+Jukie@users.noreply.github.com> --- api/v1alpha1/loadbalancer_types.go | 3 +- ....envoyproxy.io_backendtrafficpolicies.yaml | 8 +- ....envoyproxy.io_envoyextensionpolicies.yaml | 9 +- .../gateway.envoyproxy.io_envoyproxies.yaml | 40 ++++---- ...ateway.envoyproxy.io_securitypolicies.yaml | 37 ++++---- ....envoyproxy.io_backendtrafficpolicies.yaml | 8 +- ....envoyproxy.io_envoyextensionpolicies.yaml | 9 +- .../gateway.envoyproxy.io_envoyproxies.yaml | 40 ++++---- ...ateway.envoyproxy.io_securitypolicies.yaml | 37 ++++---- internal/gatewayapi/clustersettings.go | 11 +++ internal/ir/xds.go | 13 ++- internal/ir/zz_generated.deepcopy.go | 20 ++++ internal/xds/translator/cluster.go | 65 ++++++++++++- .../in/xds-ir/http-route-weighted-zones.yaml | 58 ++++++++++++ .../http-route-weighted-zones.clusters.yaml | 46 +++++++++ .../http-route-weighted-zones.endpoints.yaml | 60 ++++++++++++ .../http-route-weighted-zones.listeners.yaml | 33 +++++++ .../http-route-weighted-zones.routes.yaml | 32 +++++++ internal/xds/translator/translator.go | 4 +- site/content/en/latest/api/extension_types.md | 1 + .../backendtrafficpolicy_test.go | 63 ++++++++++++- test/helm/gateway-crds-helm/all.out.yaml | 94 ++++++++++--------- .../envoy-gateway-crds.out.yaml | 94 ++++++++++--------- 23 files changed, 609 insertions(+), 176 deletions(-) create mode 100644 internal/xds/translator/testdata/in/xds-ir/http-route-weighted-zones.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.clusters.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.endpoints.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.listeners.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.routes.yaml diff --git a/api/v1alpha1/loadbalancer_types.go b/api/v1alpha1/loadbalancer_types.go index 1bcf57de67..373fc0f261 100644 --- a/api/v1alpha1/loadbalancer_types.go +++ b/api/v1alpha1/loadbalancer_types.go @@ -12,7 +12,7 @@ import gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" // // +kubebuilder:validation:XValidation:rule="self.type == 'ConsistentHash' ? has(self.consistentHash) : !has(self.consistentHash)",message="If LoadBalancer type is consistentHash, consistentHash field needs to be set." // +kubebuilder:validation:XValidation:rule="self.type in ['Random', 'ConsistentHash'] ? !has(self.slowStart) : true ",message="Currently SlowStart is only supported for RoundRobin and LeastRequest load balancers." -// +kubebuilder:validation:XValidation:rule="self.type == 'ConsistentHash' ? !has(self.zoneAware) : true ",message="Currently ZoneAware is only supported for LeastRequest, Random, and RoundRobin load balancers." +// +kubebuilder:validation:XValidation:rule="self.type == 'ConsistentHash' && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) : true",message="PreferLocal zone-aware routing is not supported for ConsistentHash load balancers. Use weightedZones instead." // +kubebuilder:validation:XValidation:rule="has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && has(self.zoneAware.weightedZones)) : true",message="ZoneAware PreferLocal and WeightedZones cannot be specified together." type LoadBalancer struct { // Type decides the type of Load Balancer policy. @@ -190,7 +190,6 @@ type ZoneAware struct { // Traffic is distributed proportionally based on the sum of all zone weights. // // +optional - // +notImplementedHide WeightedZones []WeightedZoneConfig `json:"weightedZones,omitempty"` } diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index c402415c4c..9b9d7f1773 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -968,10 +968,10 @@ spec: LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : - true ' + - message: PreferLocal zone-aware routing is not supported for ConsistentHash + load balancers. Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) ? + !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index b710de7681..73c002dc13 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -1006,10 +1006,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml index 2e0fb3323d..06980dbb3e 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -12102,11 +12102,13 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -13401,11 +13403,13 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -14847,11 +14851,12 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported - for LeastRequest, Random, and RoundRobin - load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is + not supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && + has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -16213,10 +16218,11 @@ spec: RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for - LeastRequest, Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml index 7028a91c93..a3af73bd89 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1630,10 +1630,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -2815,10 +2816,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -4215,11 +4217,11 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported - for LeastRequest, Random, and RoundRobin load - balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not + supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -5665,10 +5667,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index dec272f233..97be89572e 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -967,10 +967,10 @@ spec: LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : - true ' + - message: PreferLocal zone-aware routing is not supported for ConsistentHash + load balancers. Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) ? + !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 49e0303c36..d95fec88d4 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -1005,10 +1005,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml index 118c4c3380..f61aad8668 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -12101,11 +12101,13 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -13400,11 +13402,13 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -14846,11 +14850,12 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported - for LeastRequest, Random, and RoundRobin - load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is + not supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && + has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -16212,10 +16217,11 @@ spec: RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for - LeastRequest, Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index 4381145a84..b392352c28 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1629,10 +1629,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -2814,10 +2815,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -4214,11 +4216,11 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported - for LeastRequest, Random, and RoundRobin load - balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not + supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -5664,10 +5666,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) diff --git a/internal/gatewayapi/clustersettings.go b/internal/gatewayapi/clustersettings.go index 867d269f6a..51c668a3a7 100644 --- a/internal/gatewayapi/clustersettings.go +++ b/internal/gatewayapi/clustersettings.go @@ -357,6 +357,17 @@ func buildLoadBalancer(policy *egv1a1.ClusterSettings) (*ir.LoadBalancer, error) } } + // Add WeightedZones loadbalancer settings + if policy.LoadBalancer.ZoneAware != nil && len(policy.LoadBalancer.ZoneAware.WeightedZones) > 0 { + lb.WeightedZones = make([]ir.WeightedZoneConfig, len(policy.LoadBalancer.ZoneAware.WeightedZones)) + for i, wz := range policy.LoadBalancer.ZoneAware.WeightedZones { + lb.WeightedZones[i] = ir.WeightedZoneConfig{ + Zone: wz.Zone, + Weight: wz.Weight, + } + } + } + // Add EndpointOverride if specified if policy.LoadBalancer.EndpointOverride != nil { lb.EndpointOverride = buildEndpointOverride(*policy.LoadBalancer.EndpointOverride) diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 7b8f10eb1f..7a9e546a88 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -881,7 +881,7 @@ func (h *HTTPRoute) GetRetry() *Retry { func (h *HTTPRoute) NeedsClusterPerSetting() bool { if h.Traffic != nil && h.Traffic.LoadBalancer != nil && - h.Traffic.LoadBalancer.PreferLocal != nil { + (h.Traffic.LoadBalancer.PreferLocal != nil || len(h.Traffic.LoadBalancer.WeightedZones) > 0) { return true } // When the destination has both valid and invalid backend weights, we use weighted clusters to distribute between @@ -2715,6 +2715,8 @@ type LoadBalancer struct { ConsistentHash *ConsistentHash `json:"consistentHash,omitempty" yaml:"consistentHash,omitempty"` // PreferLocal defines the configuration related to the distribution of requests between locality zones. PreferLocal *PreferLocalZone `json:"preferLocal,omitempty" yaml:"preferLocal,omitempty"` + // WeightedZones defines explicit weight-based traffic distribution across locality zones. + WeightedZones []WeightedZoneConfig `json:"weightedZones,omitempty" yaml:"weightedZones,omitempty"` // EndpointOverride defines the configuration for endpoint override. // When specified, the load balancer will attempt to route requests to endpoints // based on the override information extracted from request headers or metadata. @@ -3479,6 +3481,15 @@ type ForceLocalZone struct { MinEndpointsInZoneThreshold *uint32 `json:"minEndpointsInZoneThreshold,omitempty" yaml:"minEndpointsInZoneThreshold,omitempty"` } +// WeightedZoneConfig defines the weight for a specific locality zone. +// +k8s:deepcopy-gen=true +type WeightedZoneConfig struct { + // Zone is the locality zone name. + Zone string `json:"zone" yaml:"zone"` + // Weight is the proportional traffic weight for this zone. + Weight uint32 `json:"weight" yaml:"weight"` +} + // EndpointOverride defines the configuration for endpoint override. // +k8s:deepcopy-gen=true type EndpointOverride struct { diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index dc2b458f0c..5ff4c3d9c6 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -2631,6 +2631,11 @@ func (in *LoadBalancer) DeepCopyInto(out *LoadBalancer) { *out = new(PreferLocalZone) (*in).DeepCopyInto(*out) } + if in.WeightedZones != nil { + in, out := &in.WeightedZones, &out.WeightedZones + *out = make([]WeightedZoneConfig, len(*in)) + copy(*out, *in) + } if in.EndpointOverride != nil { in, out := &in.EndpointOverride, &out.EndpointOverride *out = new(EndpointOverride) @@ -4729,6 +4734,21 @@ func (in *Wasm) DeepCopy() *Wasm { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WeightedZoneConfig) DeepCopyInto(out *WeightedZoneConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WeightedZoneConfig. +func (in *WeightedZoneConfig) DeepCopy() *WeightedZoneConfig { + if in == nil { + return nil + } + out := new(WeightedZoneConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *XForwardedClientCert) DeepCopyInto(out *XForwardedClientCert) { *out = *in diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go index 0384f8dac7..2f2f39ed33 100644 --- a/internal/xds/translator/cluster.go +++ b/internal/xds/translator/cluster.go @@ -430,6 +430,10 @@ func buildXdsCluster(args *xdsClusterArgs) (*buildClusterResult, error) { if args.loadBalancer.ConsistentHash.TableSize != nil { consistentHash.TableSize = wrapperspb.UInt64(*args.loadBalancer.ConsistentHash.TableSize) } + // Enable locality weighted load balancing for Maglev when weighted zones are configured + if len(args.loadBalancer.WeightedZones) > 0 { + consistentHash.LocalityWeightedLbConfig = &commonv3.LocalityLbConfig_LocalityWeightedLbConfig{} + } typedConsistentHash, err := proto.ToAnyWithValidation(consistentHash) if err != nil { return nil, err @@ -759,7 +763,7 @@ func buildXdsClusterCircuitBreaker(circuitBreaker *ir.CircuitBreaker) *clusterv3 return ecb } -func buildXdsClusterLoadAssignment(clusterName string, destSettings []*ir.DestinationSetting, hc *ir.HealthCheck, preferLocal *ir.PreferLocalZone) *endpointv3.ClusterLoadAssignment { +func buildXdsClusterLoadAssignment(clusterName string, destSettings []*ir.DestinationSetting, hc *ir.HealthCheck, preferLocal *ir.PreferLocalZone, weightedZones []ir.WeightedZoneConfig) *endpointv3.ClusterLoadAssignment { localities := make([]*endpointv3.LocalityLbEndpoints, 0, len(destSettings)) for i, ds := range destSettings { @@ -785,6 +789,8 @@ func buildXdsClusterLoadAssignment(clusterName string, destSettings []*ir.Destin // For more details see https://github.com/envoyproxy/gateway/issues/5307#issuecomment-2688767482 if ds.PreferLocal != nil || preferLocal != nil { localities = append(localities, buildZonalLocalities(metadata, ds, hc)...) + } else if len(weightedZones) > 0 { + localities = append(localities, buildWeightedZonalLocalities(metadata, ds, hc, weightedZones)...) } else { localities = append(localities, buildWeightedLocalities(metadata, ds, hc)) } @@ -836,6 +842,63 @@ func buildZonalLocalities(metadata *corev3.Metadata, ds *ir.DestinationSetting, return localities } +func buildWeightedZonalLocalities(metadata *corev3.Metadata, ds *ir.DestinationSetting, hc *ir.HealthCheck, weightedZones []ir.WeightedZoneConfig) []*endpointv3.LocalityLbEndpoints { + // Build zone->weight lookup map + zoneWeights := make(map[string]uint32, len(weightedZones)) + for _, wz := range weightedZones { + zoneWeights[wz.Zone] = wz.Weight + } + + // Group endpoints by zone + zonalEndpoints := make(map[string][]*endpointv3.LbEndpoint) + for _, irEp := range ds.Endpoints { + healthStatus := corev3.HealthStatus_UNKNOWN + if irEp.Draining { + healthStatus = corev3.HealthStatus_DRAINING + } + lbEndpoint := &endpointv3.LbEndpoint{ + Metadata: metadata, + HostIdentifier: &endpointv3.LbEndpoint_Endpoint{ + Endpoint: &endpointv3.Endpoint{ + Hostname: ptr.Deref(irEp.Hostname, ""), + Address: buildAddress(irEp), + HealthCheckConfig: buildHealthCheckConfig(hc), + }, + }, + LoadBalancingWeight: wrapperspb.UInt32(1), + HealthStatus: healthStatus, + } + zone := ptr.Deref(irEp.Zone, "") + zonalEndpoints[zone] = append(zonalEndpoints[zone], lbEndpoint) + } + + localities := make([]*endpointv3.LocalityLbEndpoints, 0, len(zonalEndpoints)) + for zone, endPts := range zonalEndpoints { + // Look up configured weight; default to 1 if zone not explicitly listed + weight := uint32(1) + if w, ok := zoneWeights[zone]; ok { + weight = w + } + locality := &endpointv3.LocalityLbEndpoints{ + Locality: &corev3.Locality{ + Zone: zone, + }, + LbEndpoints: endPts, + LoadBalancingWeight: wrapperspb.UInt32(weight), + Priority: ptr.Deref(ds.Priority, 0), + Metadata: buildXdsMetadata(ds.Metadata), + } + localities = append(localities, locality) + } + + // Sort by zone for deterministic output + sort.Slice(localities, func(i, j int) bool { + return localities[i].Locality.Zone < localities[j].Locality.Zone + }) + + return localities +} + func buildWeightedLocalities(metadata *corev3.Metadata, ds *ir.DestinationSetting, hc *ir.HealthCheck) *endpointv3.LocalityLbEndpoints { endpoints := make([]*endpointv3.LbEndpoint, 0, len(ds.Endpoints)) diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-zones.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-zones.yaml new file mode 100644 index 0000000000..d3ca64b6e6 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-zones.yaml @@ -0,0 +1,58 @@ +http: +- name: "first-listener" + address: "::" + port: 10080 + hostnames: + - "*" + routes: + - name: "route-with-weighted-zones-roundrobin" + hostname: "*" + destination: + name: "route-with-weighted-zones-roundrobin-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 8080 + zone: us-east-1a + - host: "2.3.4.5" + port: 8080 + zone: us-east-1a + - host: "3.4.5.6" + port: 8080 + zone: us-east-1b + - host: "4.5.6.7" + port: 8080 + zone: us-east-1c + name: "route-with-weighted-zones-roundrobin-dest/backend/0" + weight: 1 + traffic: + loadBalancer: + roundRobin: {} + weightedZones: + - zone: us-east-1a + weight: 70 + - zone: us-east-1b + weight: 20 + - name: "route-with-weighted-zones-maglev" + hostname: "*" + destination: + name: "route-with-weighted-zones-maglev-dest" + settings: + - endpoints: + - host: "10.0.0.1" + port: 8080 + zone: us-west-2a + - host: "10.0.0.2" + port: 8080 + zone: us-west-2b + name: "route-with-weighted-zones-maglev-dest/backend/0" + weight: 1 + traffic: + loadBalancer: + consistentHash: + sourceIP: true + weightedZones: + - zone: us-west-2a + weight: 80 + - zone: us-west-2b + weight: 20 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.clusters.yaml new file mode 100644 index 0000000000..cb66fa7fd1 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.clusters.yaml @@ -0,0 +1,46 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: route-with-weighted-zones-roundrobin-dest/backend/0 + ignoreHealthOnHostRemoval: true + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.round_robin + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.round_robin.v3.RoundRobin + localityLbConfig: + localityWeightedLbConfig: {} + name: route-with-weighted-zones-roundrobin-dest/backend/0 + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: route-with-weighted-zones-maglev-dest/backend/0 + ignoreHealthOnHostRemoval: true + lbPolicy: MAGLEV + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.maglev + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.maglev.v3.Maglev + localityWeightedLbConfig: {} + name: route-with-weighted-zones-maglev-dest/backend/0 + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.endpoints.yaml new file mode 100644 index 0000000000..694bdbf80f --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.endpoints.yaml @@ -0,0 +1,60 @@ +- clusterName: route-with-weighted-zones-roundrobin-dest/backend/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 8080 + loadBalancingWeight: 1 + - endpoint: + address: + socketAddress: + address: 2.3.4.5 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 70 + locality: + zone: us-east-1a + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 3.4.5.6 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + zone: us-east-1b + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 4.5.6.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + zone: us-east-1c +- clusterName: route-with-weighted-zones-maglev-dest/backend/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 80 + locality: + zone: us-west-2a + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.2 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + zone: us-west-2b diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.listeners.yaml new file mode 100644 index 0000000000..5c7db41545 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.listeners.yaml @@ -0,0 +1,33 @@ +- address: + socketAddress: + address: '::' + portValue: 10080 + defaultFilterChain: + filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + commonHttpProtocolOptions: + headersWithUnderscoresAction: REJECT_REQUEST + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + normalizePath: true + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http-10080 + useRemoteAddress: true + name: first-listener + maxConnectionsToAcceptPerSocketEvent: 1 + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.routes.yaml new file mode 100644 index 0000000000..ecca8196e4 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-zones.routes.yaml @@ -0,0 +1,32 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: route-with-weighted-zones-roundrobin + route: + clusterNotFoundResponseCode: INTERNAL_SERVER_ERROR + upgradeConfigs: + - upgradeType: websocket + weightedClusters: + clusters: + - name: route-with-weighted-zones-roundrobin-dest/backend/0 + weight: 1 + - match: + prefix: / + name: route-with-weighted-zones-maglev + route: + clusterNotFoundResponseCode: INTERNAL_SERVER_ERROR + hashPolicy: + - connectionProperties: + sourceIp: true + upgradeConfigs: + - upgradeType: websocket + weightedClusters: + clusters: + - name: route-with-weighted-zones-maglev-dest/backend/0 + weight: 1 diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index 1993afb209..f15c41f199 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -1103,8 +1103,8 @@ func addXdsCluster(tCtx *types.ResourceVersionTable, args *xdsClusterArgs) error return err } xdsCluster := result.cluster - preferLocal := ptr.Deref(args.loadBalancer, ir.LoadBalancer{}).PreferLocal - xdsEndpoints := buildXdsClusterLoadAssignment(args.name, args.settings, args.healthCheck, preferLocal) + lb := ptr.Deref(args.loadBalancer, ir.LoadBalancer{}) + xdsEndpoints := buildXdsClusterLoadAssignment(args.name, args.settings, args.healthCheck, lb.PreferLocal, lb.WeightedZones) for _, ds := range args.settings { shouldValidateTLS := ds.TLS != nil && !ds.TLS.InsecureSkipVerify if shouldValidateTLS { diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 5ce6b2f2ac..2253f76ab0 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -5897,6 +5897,7 @@ _Appears in:_ | Field | Type | Required | Default | Description | | --- | --- | --- | --- | --- | | `preferLocal` | _[PreferLocalZone](#preferlocalzone)_ | false | | PreferLocalZone configures zone-aware routing to prefer sending traffic to the local locality zone. | +| `weightedZones` | _[WeightedZoneConfig](#weightedzoneconfig) array_ | false | | WeightedZones configures weight-based traffic distribution across locality zones.
Traffic is distributed proportionally based on the sum of all zone weights. | #### ZstdCompressor diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index 858c21d447..d2d6aa3d55 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -349,7 +349,7 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, { - desc: "consistentHash lb with zoneAware", + desc: "consistentHash lb with empty zoneAware", mutate: func(btp *egv1a1.BackendTrafficPolicy) { btp.Spec = egv1a1.BackendTrafficPolicySpec{ PolicyTargetReferences: egv1a1.PolicyTargetReferences{ @@ -372,11 +372,70 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, } }, + wantErrors: []string{}, + }, + { + desc: "consistentHash lb with zoneAware preferLocal", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetRef: &gwapiv1.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1.LocalPolicyTargetReference{ + Group: gwapiv1.Group("gateway.networking.k8s.io"), + Kind: gwapiv1.Kind("Gateway"), + Name: gwapiv1.ObjectName("eg"), + }, + }, + }, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + ConsistentHash: &egv1a1.ConsistentHash{ + Type: "SourceIP", + }, + ZoneAware: &egv1a1.ZoneAware{ + PreferLocal: &egv1a1.PreferLocalZone{}, + }, + }, + }, + } + }, wantErrors: []string{ "spec.loadBalancer: Invalid value:", - ": Currently ZoneAware is only supported for LeastRequest, Random, and RoundRobin load balancers", + ": PreferLocal zone-aware routing is not supported for ConsistentHash load balancers. Use weightedZones instead.", }, }, + { + desc: "consistentHash lb with zoneAware weightedZones", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetRef: &gwapiv1.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1.LocalPolicyTargetReference{ + Group: gwapiv1.Group("gateway.networking.k8s.io"), + Kind: gwapiv1.Kind("Gateway"), + Name: gwapiv1.ObjectName("eg"), + }, + }, + }, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + ConsistentHash: &egv1a1.ConsistentHash{ + Type: "SourceIP", + }, + ZoneAware: &egv1a1.ZoneAware{ + WeightedZones: []egv1a1.WeightedZoneConfig{{ + Zone: "us-east-1a", + Weight: uint32(70), + }}, + }, + }, + }, + } + }, + wantErrors: []string{}, + }, { desc: "leastRequest with ConsistentHash nil", mutate: func(btp *egv1a1.BackendTrafficPolicy) { diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml index 8c0a6aeae9..4f03bfeabd 100644 --- a/test/helm/gateway-crds-helm/all.out.yaml +++ b/test/helm/gateway-crds-helm/all.out.yaml @@ -22267,10 +22267,10 @@ spec: LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : - true ' + - message: PreferLocal zone-aware routing is not supported for ConsistentHash + load balancers. Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) ? + !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && @@ -27241,10 +27241,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -41061,11 +41062,13 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -42360,11 +42363,13 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -43806,11 +43811,12 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported - for LeastRequest, Random, and RoundRobin - load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is + not supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && + has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -45172,10 +45178,11 @@ spec: RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for - LeastRequest, Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -47879,10 +47886,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -49064,10 +49072,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -50464,11 +50473,11 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported - for LeastRequest, Random, and RoundRobin load - balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not + supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -51914,10 +51923,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml index 60b82af41a..3b56e5ba96 100644 --- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml +++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml @@ -1447,10 +1447,10 @@ spec: LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) : - true ' + - message: PreferLocal zone-aware routing is not supported for ConsistentHash + load balancers. Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) ? + !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) && @@ -6421,10 +6421,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -20241,11 +20242,13 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -21540,11 +21543,13 @@ spec: load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only - supported for LeastRequest, Random, - and RoundRobin load balancers. + - message: PreferLocal zone-aware routing + is not supported for ConsistentHash + load balancers. Use weightedZones + instead. rule: 'self.type == ''ConsistentHash'' - ? !has(self.zoneAware) : true ' + && has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -22986,11 +22991,12 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported - for LeastRequest, Random, and RoundRobin - load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is + not supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && + has(self.zoneAware) ? !has(self.zoneAware.preferLocal) + : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -24352,10 +24358,11 @@ spec: RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for - LeastRequest, Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -27059,10 +27066,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -28244,10 +28252,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -29644,11 +29653,11 @@ spec: for RoundRobin and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported - for LeastRequest, Random, and RoundRobin load - balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not + supported for ConsistentHash load balancers. + Use weightedZones instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) @@ -31094,10 +31103,11 @@ spec: and LeastRequest load balancers. rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStart) : true ' - - message: Currently ZoneAware is only supported for LeastRequest, - Random, and RoundRobin load balancers. - rule: 'self.type == ''ConsistentHash'' ? !has(self.zoneAware) - : true ' + - message: PreferLocal zone-aware routing is not supported + for ConsistentHash load balancers. Use weightedZones + instead. + rule: 'self.type == ''ConsistentHash'' && has(self.zoneAware) + ? !has(self.zoneAware.preferLocal) : true' - message: ZoneAware PreferLocal and WeightedZones cannot be specified together. rule: 'has(self.zoneAware) ? !(has(self.zoneAware.preferLocal) From 6556bc061788eec433fec578a9e5ba042b324691 Mon Sep 17 00:00:00 2001 From: jukie <10012479+Jukie@users.noreply.github.com> Date: Thu, 5 Feb 2026 23:29:40 -0700 Subject: [PATCH 06/13] Fix cel test and PR feedback Signed-off-by: jukie <10012479+Jukie@users.noreply.github.com> --- api/v1alpha1/loadbalancer_types.go | 6 +- ....envoyproxy.io_backendtrafficpolicies.yaml | 6 +- ....envoyproxy.io_envoyextensionpolicies.yaml | 6 +- .../gateway.envoyproxy.io_envoyproxies.yaml | 24 +++++--- ...ateway.envoyproxy.io_securitypolicies.yaml | 24 +++++--- ....envoyproxy.io_backendtrafficpolicies.yaml | 6 +- ....envoyproxy.io_envoyextensionpolicies.yaml | 6 +- .../gateway.envoyproxy.io_envoyproxies.yaml | 24 +++++--- ...ateway.envoyproxy.io_securitypolicies.yaml | 24 +++++--- site/content/en/latest/api/extension_types.md | 2 +- .../backendtrafficpolicy_test.go | 3 +- test/helm/gateway-crds-helm/all.out.yaml | 60 ++++++++++++------- .../envoy-gateway-crds.out.yaml | 60 ++++++++++++------- 13 files changed, 167 insertions(+), 84 deletions(-) diff --git a/api/v1alpha1/loadbalancer_types.go b/api/v1alpha1/loadbalancer_types.go index 373fc0f261..627c957b2c 100644 --- a/api/v1alpha1/loadbalancer_types.go +++ b/api/v1alpha1/loadbalancer_types.go @@ -226,8 +226,10 @@ type ForceLocalZone struct { // WeightedZoneConfig defines the weight for a specific locality zone. type WeightedZoneConfig struct { - // Zone specifies the zone this weight applies to. - // Empty string means apply to all zones within the region. + // Zone specifies the topology zone this weight applies to. + // The value should match the topology.kubernetes.io/zone label + // of the nodes where endpoints are running. + // Zones not listed in the configuration receive a default weight of 1. Zone string `json:"zone,omitempty"` // Weight defines the weight for this locality. diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index 9b9d7f1773..93aa9b575b 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -948,8 +948,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 73c002dc13..c2acc3aa8c 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -986,8 +986,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml index 06980dbb3e..91c32bbb4e 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -12081,8 +12081,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -13382,8 +13384,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -14831,8 +14835,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -16198,8 +16204,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml index a3af73bd89..946867f99b 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1610,8 +1610,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -2796,8 +2798,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -4197,8 +4201,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -5647,8 +5653,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index 97be89572e..9e8742e632 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -947,8 +947,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index d95fec88d4..267cc185ab 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -985,8 +985,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml index f61aad8668..de76a962f6 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -12080,8 +12080,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -13381,8 +13383,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -14830,8 +14834,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -16197,8 +16203,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index b392352c28..118a8f28f5 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1609,8 +1609,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -2795,8 +2797,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -4196,8 +4200,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -5646,8 +5652,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 2253f76ab0..6d8839375d 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -5730,7 +5730,7 @@ _Appears in:_ | Field | Type | Required | Default | Description | | --- | --- | --- | --- | --- | -| `zone` | _string_ | true | | Zone specifies the zone this weight applies to.
Empty string means apply to all zones within the region. | +| `zone` | _string_ | true | | Zone specifies the topology zone this weight applies to.
The value should match the topology.kubernetes.io/zone label
of the nodes where endpoints are running.
Zones not listed in the configuration receive a default weight of 1. | | `weight` | _integer_ | true | | Weight defines the weight for this locality.
Higher values receive more traffic. The actual traffic distribution
is proportional to this value relative to other localities. | diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index d2d6aa3d55..00e2a8932b 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -509,7 +509,8 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { } }, wantErrors: []string{ - "spec.loadBalancer: Invalid value: \"object\": ZoneAware PreferLocal and WeightedZones cannot be specified together", + "spec.loadBalancer: Invalid value:", + ": ZoneAware PreferLocal and WeightedZones cannot be specified together", }, }, { diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml index 4f03bfeabd..848a128e23 100644 --- a/test/helm/gateway-crds-helm/all.out.yaml +++ b/test/helm/gateway-crds-helm/all.out.yaml @@ -22247,8 +22247,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -27221,8 +27223,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -41041,8 +41045,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -42342,8 +42348,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -43791,8 +43799,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -45158,8 +45168,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -47866,8 +47878,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -49052,8 +49066,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -50453,8 +50469,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -51903,8 +51921,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml index 3b56e5ba96..dac7cde7b2 100644 --- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml +++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml @@ -1427,8 +1427,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -6401,8 +6403,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -20221,8 +20225,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -21522,8 +21528,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -22971,8 +22979,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -24338,8 +24348,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -27046,8 +27058,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -28232,8 +28246,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -29633,8 +29649,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight @@ -31083,8 +31101,10 @@ spec: type: integer zone: description: |- - Zone specifies the zone this weight applies to. - Empty string means apply to all zones within the region. + Zone specifies the topology zone this weight applies to. + The value should match the topology.kubernetes.io/zone label + of the nodes where endpoints are running. + Zones not listed in the configuration receive a default weight of 1. type: string required: - weight From 69fb84705938ead4290796f90e5cf3c0ab633ccb Mon Sep 17 00:00:00 2001 From: jukie <10012479+Jukie@users.noreply.github.com> Date: Thu, 5 Feb 2026 23:41:45 -0700 Subject: [PATCH 07/13] lint Signed-off-by: jukie <10012479+Jukie@users.noreply.github.com> --- internal/xds/translator/cluster.go | 7 ++++--- release-notes/current.yaml | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go index 2f2f39ed33..d38a6ecb78 100644 --- a/internal/xds/translator/cluster.go +++ b/internal/xds/translator/cluster.go @@ -787,11 +787,12 @@ func buildXdsClusterLoadAssignment(clusterName string, destSettings []*ir.Destin // if multiple backendRefs exist. This pushes part of the routing logic higher up the stack which can // limit host selection controls during retries and session affinity. // For more details see https://github.com/envoyproxy/gateway/issues/5307#issuecomment-2688767482 - if ds.PreferLocal != nil || preferLocal != nil { + switch { + case ds.PreferLocal != nil || preferLocal != nil: localities = append(localities, buildZonalLocalities(metadata, ds, hc)...) - } else if len(weightedZones) > 0 { + case len(weightedZones) > 0: localities = append(localities, buildWeightedZonalLocalities(metadata, ds, hc, weightedZones)...) - } else { + default: localities = append(localities, buildWeightedLocalities(metadata, ds, hc)) } } diff --git a/release-notes/current.yaml b/release-notes/current.yaml index 1faf4c4c4c..ee257107d7 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -9,6 +9,7 @@ security updates: | # New features or capabilities added in this release. new features: | Added support for configuring optional health check configuration. + Support for configuring weights for locality zones bug fixes: | Rejected ClientTrafficPolicy if invalid TLS cipher suites are configured. From 30d48c7bd72d8f56d8574bab2da5edce37156424 Mon Sep 17 00:00:00 2001 From: jukie <10012479+Jukie@users.noreply.github.com> Date: Fri, 6 Feb 2026 11:43:53 -0700 Subject: [PATCH 08/13] e2e Signed-off-by: jukie <10012479+Jukie@users.noreply.github.com> --- test/e2e/testdata/weighted-zones.yaml | 129 ++++++++++++++++++++++++++ test/e2e/tests/weighted_zones.go | 58 ++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 test/e2e/testdata/weighted-zones.yaml create mode 100644 test/e2e/tests/weighted_zones.go diff --git a/test/e2e/testdata/weighted-zones.yaml b/test/e2e/testdata/weighted-zones.yaml new file mode 100644 index 0000000000..979652dcf7 --- /dev/null +++ b/test/e2e/testdata/weighted-zones.yaml @@ -0,0 +1,129 @@ +apiVersion: v1 +kind: Service +metadata: + name: weighted-zones-backend + namespace: gateway-conformance-infra +spec: + selector: + app: weighted-zones-backend + ports: + - protocol: TCP + port: 8080 + name: http11 + targetPort: 3000 +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: weighted-zones-route + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /weighted-zones + backendRefs: + - name: weighted-zones-backend + port: 8080 +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: BackendTrafficPolicy +metadata: + name: weighted-zones-policy + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: weighted-zones-route + loadBalancer: + type: RoundRobin + zoneAware: + weightedZones: + - zone: "1" + weight: 80 + - zone: "2" + weight: 20 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: weighted-zones-backend-zone1 + namespace: gateway-conformance-infra + labels: + app: weighted-zones-backend +spec: + replicas: 1 + selector: + matchLabels: + app: weighted-zones-backend + zone: "1" + template: + metadata: + labels: + app: weighted-zones-backend + zone: "1" + spec: + nodeSelector: + topology.kubernetes.io/zone: "1" + containers: + - name: weighted-zones-backend + # From https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/echo-basic/echo-basic.go + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SERVICE_NAME + value: weighted-zones-backend + resources: + requests: + cpu: 10m +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: weighted-zones-backend-zone2 + namespace: gateway-conformance-infra + labels: + app: weighted-zones-backend +spec: + replicas: 1 + selector: + matchLabels: + app: weighted-zones-backend + zone: "2" + template: + metadata: + labels: + app: weighted-zones-backend + zone: "2" + spec: + nodeSelector: + topology.kubernetes.io/zone: "2" + containers: + - name: weighted-zones-backend + # From https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/echo-basic/echo-basic.go + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SERVICE_NAME + value: weighted-zones-backend + resources: + requests: + cpu: 10m diff --git a/test/e2e/tests/weighted_zones.go b/test/e2e/tests/weighted_zones.go new file mode 100644 index 0000000000..dbc333cffd --- /dev/null +++ b/test/e2e/tests/weighted_zones.go @@ -0,0 +1,58 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +//go:build e2e + +package tests + +import ( + "math" + "testing" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + + "github.com/envoyproxy/gateway/internal/gatewayapi" + "github.com/envoyproxy/gateway/internal/gatewayapi/resource" +) + +func init() { + ConformanceTests = append(ConformanceTests, WeightedZonesTest) +} + +var WeightedZonesTest = suite.ConformanceTest{ + ShortName: "WeightedZones", + Description: "Test weighted zone traffic distribution via BackendTrafficPolicy", + Manifests: []string{"testdata/weighted-zones.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + + WaitForPods(t, suite.Client, ns, map[string]string{"app": "weighted-zones-backend"}, corev1.PodRunning, &PodReady) + + BackendTrafficPolicyMustBeAccepted(t, + suite.Client, + types.NamespacedName{Name: "weighted-zones-policy", Namespace: ns}, + suite.ControllerName, + gwapiv1.ParentReference{ + Group: gatewayapi.GroupPtr(gwapiv1.GroupName), + Kind: gatewayapi.KindPtr(resource.KindGateway), + Namespace: gatewayapi.NamespacePtr(ns), + Name: gwapiv1.ObjectName("same-namespace"), + }, + ) + + t.Run("traffic should be distributed according to zone weights", func(t *testing.T) { + // BTP configures zone "1" with weight 80 and zone "2" with weight 20. + // Deployments pin one pod per zone via nodeSelector. + expected := map[string]int{ + "weighted-zones-backend-zone1": int(math.Round(sendRequests * 0.80)), + "weighted-zones-backend-zone2": int(math.Round(sendRequests * 0.20)), + } + runWeightedBackendTest(t, suite, nil, "weighted-zones-route", "/weighted-zones", "weighted-zones-backend", expected) + }) + }, +} From 815393ba01df8dc018c89be3dd0a0d38f540f355 Mon Sep 17 00:00:00 2001 From: jukie <10012479+Jukie@users.noreply.github.com> Date: Sun, 8 Feb 2026 13:52:06 -0700 Subject: [PATCH 09/13] remove omitempty, add cel-validation for duplicate zones Signed-off-by: jukie <10012479+Jukie@users.noreply.github.com> --- api/v1alpha1/loadbalancer_types.go | 4 +- api/v1alpha1/zz_generated.deepcopy.go | 652 +++++++++++++++++- ....envoyproxy.io_backendtrafficpolicies.yaml | 5 + ....envoyproxy.io_envoyextensionpolicies.yaml | 5 + .../gateway.envoyproxy.io_envoyproxies.yaml | 28 + ...ateway.envoyproxy.io_securitypolicies.yaml | 25 + ....envoyproxy.io_backendtrafficpolicies.yaml | 5 + ....envoyproxy.io_envoyextensionpolicies.yaml | 5 + .../gateway.envoyproxy.io_envoyproxies.yaml | 28 + ...ateway.envoyproxy.io_securitypolicies.yaml | 25 + internal/xds/translator/cluster_test.go | 4 +- release-notes/current.yaml | 2 +- .../backendtrafficpolicy_test.go | 31 + test/helm/gateway-crds-helm/all.out.yaml | 63 ++ .../envoy-gateway-crds.out.yaml | 63 ++ 15 files changed, 920 insertions(+), 25 deletions(-) diff --git a/api/v1alpha1/loadbalancer_types.go b/api/v1alpha1/loadbalancer_types.go index 627c957b2c..d2b343b588 100644 --- a/api/v1alpha1/loadbalancer_types.go +++ b/api/v1alpha1/loadbalancer_types.go @@ -180,6 +180,8 @@ type SlowStart struct { } // ZoneAware defines the configuration related to the distribution of requests between locality zones. +// +// +kubebuilder:validation:XValidation:rule="!has(self.weightedZones) || self.weightedZones.all(z, self.weightedZones.exists_one(z2, z2.zone == z.zone))",message="Duplicate zone names are not allowed in weightedZones." type ZoneAware struct { // PreferLocalZone configures zone-aware routing to prefer sending traffic to the local locality zone. // @@ -230,7 +232,7 @@ type WeightedZoneConfig struct { // The value should match the topology.kubernetes.io/zone label // of the nodes where endpoints are running. // Zones not listed in the configuration receive a default weight of 1. - Zone string `json:"zone,omitempty"` + Zone string `json:"zone"` // Weight defines the weight for this locality. // Higher values receive more traffic. The actual traffic distribution diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 429e100fc8..74b498de25 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -15,11 +15,9 @@ import ( corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/gateway-api/apis/v1" - "sigs.k8s.io/gateway-api/apis/v1alpha2" - "sigs.k8s.io/gateway-api/apis/v1alpha3" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -164,6 +162,11 @@ func (in *ActiveHealthCheck) DeepCopyInto(out *ActiveHealthCheck) { *out = new(GRPCActiveHealthChecker) (*in).DeepCopyInto(*out) } + if in.Overrides != nil { + in, out := &in.Overrides, &out.Overrides + *out = new(HealthCheckOverrides) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveHealthCheck. @@ -371,6 +374,11 @@ func (in *BackendConnection) DeepCopyInto(out *BackendConnection) { x := (*in).DeepCopy() *out = &x } + if in.Preconnect != nil { + in, out := &in.Preconnect, &out.Preconnect + *out = new(PreconnectPolicy) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendConnection. @@ -455,10 +463,35 @@ func (in *BackendList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendMetrics) DeepCopyInto(out *BackendMetrics) { + *out = *in + if in.RouteStatName != nil { + in, out := &in.RouteStatName, &out.RouteStatName + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendMetrics. +func (in *BackendMetrics) DeepCopy() *BackendMetrics { + if in == nil { + return nil + } + out := new(BackendMetrics) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendRef) DeepCopyInto(out *BackendRef) { *out = *in in.BackendObjectReference.DeepCopyInto(&out.BackendObjectReference) + if in.Weight != nil { + in, out := &in.Weight, &out.Weight + *out = new(uint32) + **out = **in + } if in.Fallback != nil { in, out := &in.Fallback, &out.Fallback *out = new(bool) @@ -571,7 +604,7 @@ func (in *BackendTLSSettings) DeepCopyInto(out *BackendTLSSettings) { } if in.WellKnownCACertificates != nil { in, out := &in.WellKnownCACertificates, &out.WellKnownCACertificates - *out = new(v1alpha3.WellKnownCACertificatesType) + *out = new(v1.WellKnownCACertificatesType) **out = **in } if in.InsecureSkipVerify != nil { @@ -584,6 +617,11 @@ func (in *BackendTLSSettings) DeepCopyInto(out *BackendTLSSettings) { *out = new(v1.PreciseHostname) **out = **in } + if in.BackendTLSConfig != nil { + in, out := &in.BackendTLSConfig, &out.BackendTLSConfig + *out = new(BackendTLSConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSSettings. @@ -604,6 +642,11 @@ func (in *BackendTelemetry) DeepCopyInto(out *BackendTelemetry) { *out = new(Tracing) (*in).DeepCopyInto(*out) } + if in.Metrics != nil { + in, out := &in.Metrics, &out.Metrics + *out = new(BackendMetrics) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTelemetry. @@ -711,6 +754,17 @@ func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec) } } } + if in.Compressor != nil { + in, out := &in.Compressor, &out.Compressor + *out = make([]*Compression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Compression) + (*in).DeepCopyInto(*out) + } + } + } if in.ResponseOverride != nil { in, out := &in.ResponseOverride, &out.ResponseOverride *out = make([]*ResponseOverride, len(*in)) @@ -743,6 +797,11 @@ func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec) *out = new(BackendTelemetry) (*in).DeepCopyInto(*out) } + if in.RoutingType != nil { + in, out := &in.RoutingType, &out.RoutingType + *out = new(RoutingType) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTrafficPolicySpec. @@ -1150,6 +1209,11 @@ func (in *ClientTrafficPolicySpec) DeepCopyInto(out *ClientTrafficPolicySpec) { *out = new(HealthCheckSettings) **out = **in } + if in.Scheme != nil { + in, out := &in.Scheme, &out.Scheme + *out = new(SchemeHeaderTransform) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientTrafficPolicySpec. @@ -1302,6 +1366,16 @@ func (in *Compression) DeepCopyInto(out *Compression) { *out = new(GzipCompressor) **out = **in } + if in.Zstd != nil { + in, out := &in.Zstd, &out.Zstd + *out = new(ZstdCompressor) + **out = **in + } + if in.MinContentLength != nil { + in, out := &in.MinContentLength, &out.MinContentLength + x := (*in).DeepCopy() + *out = &x + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Compression. @@ -1377,11 +1451,33 @@ func (in *ConsistentHash) DeepCopyInto(out *ConsistentHash) { *out = new(Header) **out = **in } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]*Header, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Header) + **out = **in + } + } + } if in.Cookie != nil { in, out := &in.Cookie, &out.Cookie *out = new(Cookie) (*in).DeepCopyInto(*out) } + if in.QueryParams != nil { + in, out := &in.QueryParams, &out.QueryParams + *out = make([]*QueryParam, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(QueryParam) + **out = **in + } + } + } if in.TableSize != nil { in, out := &in.TableSize, &out.TableSize *out = new(uint64) @@ -1399,6 +1495,31 @@ func (in *ConsistentHash) DeepCopy() *ConsistentHash { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ContextExtension) DeepCopyInto(out *ContextExtension) { + *out = *in + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(string) + **out = **in + } + if in.ValueRef != nil { + in, out := &in.ValueRef, &out.ValueRef + *out = new(LocalObjectKeyReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContextExtension. +func (in *ContextExtension) DeepCopy() *ContextExtension { + if in == nil { + return nil + } + out := new(ContextExtension) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Cookie) DeepCopyInto(out *Cookie) { *out = *in @@ -1922,6 +2043,26 @@ func (in *EnvoyGatewayFileResourceProvider) DeepCopy() *EnvoyGatewayFileResource // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EnvoyGatewayHostInfrastructureProvider) DeepCopyInto(out *EnvoyGatewayHostInfrastructureProvider) { *out = *in + if in.ConfigHome != nil { + in, out := &in.ConfigHome, &out.ConfigHome + *out = new(string) + **out = **in + } + if in.DataHome != nil { + in, out := &in.DataHome, &out.DataHome + *out = new(string) + **out = **in + } + if in.StateHome != nil { + in, out := &in.StateHome, &out.StateHome + *out = new(string) + **out = **in + } + if in.RuntimeDir != nil { + in, out := &in.RuntimeDir, &out.RuntimeDir + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyGatewayHostInfrastructureProvider. @@ -1940,7 +2081,7 @@ func (in *EnvoyGatewayInfrastructureProvider) DeepCopyInto(out *EnvoyGatewayInfr if in.Host != nil { in, out := &in.Host, &out.Host *out = new(EnvoyGatewayHostInfrastructureProvider) - **out = **in + (*in).DeepCopyInto(*out) } } @@ -1967,6 +2108,11 @@ func (in *EnvoyGatewayKubernetesProvider) DeepCopyInto(out *EnvoyGatewayKubernet *out = new(KubernetesHorizontalPodAutoscalerSpec) (*in).DeepCopyInto(*out) } + if in.RateLimitPDB != nil { + in, out := &in.RateLimitPDB, &out.RateLimitPDB + *out = new(KubernetesPodDisruptionBudgetSpec) + (*in).DeepCopyInto(*out) + } if in.Watch != nil { in, out := &in.Watch, &out.Watch *out = new(KubernetesWatchMode) @@ -2024,6 +2170,11 @@ func (in *EnvoyGatewayLogging) DeepCopyInto(out *EnvoyGatewayLogging) { (*out)[key] = val } } + if in.Encoder != nil { + in, out := &in.Encoder, &out.Encoder + *out = new(EnvoyGatewayLogEncoder) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyGatewayLogging. @@ -2196,6 +2347,11 @@ func (in *EnvoyGatewaySpec) DeepCopyInto(out *EnvoyGatewaySpec) { *out = new(EnvoyGatewayTelemetry) (*in).DeepCopyInto(*out) } + if in.XDSServer != nil { + in, out := &in.XDSServer, &out.XDSServer + *out = new(XDSServer) + (*in).DeepCopyInto(*out) + } if in.RateLimit != nil { in, out := &in.RateLimit, &out.RateLimit *out = new(RateLimit) @@ -2211,11 +2367,21 @@ func (in *EnvoyGatewaySpec) DeepCopyInto(out *EnvoyGatewaySpec) { *out = new(ExtensionAPISettings) **out = **in } + if in.GatewayAPI != nil { + in, out := &in.GatewayAPI, &out.GatewayAPI + *out = new(GatewayAPISettings) + (*in).DeepCopyInto(*out) + } if in.RuntimeFlags != nil { in, out := &in.RuntimeFlags, &out.RuntimeFlags *out = new(RuntimeFlags) (*in).DeepCopyInto(*out) } + if in.EnvoyProxy != nil { + in, out := &in.EnvoyProxy, &out.EnvoyProxy + *out = new(EnvoyProxySpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyGatewaySpec. @@ -2353,7 +2519,7 @@ func (in *EnvoyPatchPolicySpec) DeepCopyInto(out *EnvoyPatchPolicySpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - in.TargetRef.DeepCopyInto(&out.TargetRef) + out.TargetRef = in.TargetRef } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyPatchPolicySpec. @@ -2372,7 +2538,7 @@ func (in *EnvoyProxy) DeepCopyInto(out *EnvoyProxy) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status + in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyProxy. @@ -2393,6 +2559,29 @@ func (in *EnvoyProxy) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvoyProxyAncestorStatus) DeepCopyInto(out *EnvoyProxyAncestorStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.AncestorRef.DeepCopyInto(&out.AncestorRef) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyProxyAncestorStatus. +func (in *EnvoyProxyAncestorStatus) DeepCopy() *EnvoyProxyAncestorStatus { + if in == nil { + return nil + } + out := new(EnvoyProxyAncestorStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EnvoyProxyHostProvider) DeepCopyInto(out *EnvoyProxyHostProvider) { *out = *in @@ -2606,6 +2795,13 @@ func (in *EnvoyProxySpec) DeepCopy() *EnvoyProxySpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EnvoyProxyStatus) DeepCopyInto(out *EnvoyProxyStatus) { *out = *in + if in.Ancestors != nil { + in, out := &in.Ancestors, &out.Ancestors + *out = make([]EnvoyProxyAncestorStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyProxyStatus. @@ -2656,6 +2852,17 @@ func (in *ExtAuth) DeepCopyInto(out *ExtAuth) { *out = new(bool) **out = **in } + if in.ContextExtensions != nil { + in, out := &in.ContextExtensions, &out.ContextExtensions + *out = make([]*ContextExtension, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(ContextExtension) + (*in).DeepCopyInto(*out) + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtAuth. @@ -3157,6 +3364,26 @@ func (in *Gateway) DeepCopy() *Gateway { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayAPISettings) DeepCopyInto(out *GatewayAPISettings) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = make([]GatewayAPI, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayAPISettings. +func (in *GatewayAPISettings) DeepCopy() *GatewayAPISettings { + if in == nil { + return nil + } + out := new(GatewayAPISettings) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GlobalRateLimit) DeepCopyInto(out *GlobalRateLimit) { *out = *in @@ -3379,6 +3606,26 @@ func (in *HTTPClientTimeout) DeepCopy() *HTTPClientTimeout { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPCookieMatch) DeepCopyInto(out *HTTPCookieMatch) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(CookieMatchType) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPCookieMatch. +func (in *HTTPCookieMatch) DeepCopy() *HTTPCookieMatch { + if in == nil { + return nil + } + out := new(HTTPCookieMatch) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPCredentialInjectionFilter) DeepCopyInto(out *HTTPCredentialInjectionFilter) { *out = *in @@ -3479,11 +3726,23 @@ func (in *HTTPHeaderFilter) DeepCopyInto(out *HTTPHeaderFilter) { *out = make([]v1.HTTPHeader, len(*in)) copy(*out, *in) } + if in.AddIfAbsent != nil { + in, out := &in.AddIfAbsent, &out.AddIfAbsent + *out = make([]v1.HTTPHeader, len(*in)) + copy(*out, *in) + } if in.Remove != nil { in, out := &in.Remove, &out.Remove *out = make([]string, len(*in)) copy(*out, *in) } + if in.RemoveOnMatch != nil { + in, out := &in.RemoveOnMatch, &out.RemoveOnMatch + *out = make([]StringMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeaderFilter. @@ -3612,6 +3871,13 @@ func (in *HTTPRouteFilterSpec) DeepCopyInto(out *HTTPRouteFilterSpec) { *out = new(HTTPCredentialInjectionFilter) (*in).DeepCopyInto(*out) } + if in.Matches != nil { + in, out := &in.Matches, &out.Matches + *out = make([]HTTPRouteMatchFilter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteFilterSpec. @@ -3624,6 +3890,28 @@ func (in *HTTPRouteFilterSpec) DeepCopy() *HTTPRouteFilterSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteMatchFilter) DeepCopyInto(out *HTTPRouteMatchFilter) { + *out = *in + if in.Cookies != nil { + in, out := &in.Cookies, &out.Cookies + *out = make([]HTTPCookieMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteMatchFilter. +func (in *HTTPRouteMatchFilter) DeepCopy() *HTTPRouteMatchFilter { + if in == nil { + return nil + } + out := new(HTTPRouteMatchFilter) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPTimeout) DeepCopyInto(out *HTTPTimeout) { *out = *in @@ -3642,6 +3930,11 @@ func (in *HTTPTimeout) DeepCopyInto(out *HTTPTimeout) { *out = new(v1.Duration) **out = **in } + if in.MaxStreamDuration != nil { + in, out := &in.MaxStreamDuration, &out.MaxStreamDuration + *out = new(v1.Duration) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPTimeout. @@ -3834,6 +4127,21 @@ func (in *HealthCheck) DeepCopy() *HealthCheck { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HealthCheckOverrides) DeepCopyInto(out *HealthCheckOverrides) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthCheckOverrides. +func (in *HealthCheckOverrides) DeepCopy() *HealthCheckOverrides { + if in == nil { + return nil + } + out := new(HealthCheckOverrides) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HealthCheckSettings) DeepCopyInto(out *HealthCheckSettings) { *out = *in @@ -4490,6 +4798,11 @@ func (in *KubernetesPodSpec) DeepCopyInto(out *KubernetesPodSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.PriorityClassName != nil { + in, out := &in.PriorityClassName, &out.PriorityClassName + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesPodSpec. @@ -4751,6 +5064,22 @@ func (in *LocalJWKS) DeepCopy() *LocalJWKS { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LocalObjectKeyReference) DeepCopyInto(out *LocalObjectKeyReference) { + *out = *in + out.LocalObjectReference = in.LocalObjectReference +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalObjectKeyReference. +func (in *LocalObjectKeyReference) DeepCopy() *LocalObjectKeyReference { + if in == nil { + return nil + } + out := new(LocalObjectKeyReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LocalRateLimit) DeepCopyInto(out *LocalRateLimit) { *out = *in @@ -4798,6 +5127,26 @@ func (in *Lua) DeepCopy() *Lua { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MethodMatch) DeepCopyInto(out *MethodMatch) { + *out = *in + if in.Invert != nil { + in, out := &in.Invert, &out.Invert + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MethodMatch. +func (in *MethodMatch) DeepCopy() *MethodMatch { + if in == nil { + return nil + } + out := new(MethodMatch) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OIDC) DeepCopyInto(out *OIDC) { *out = *in @@ -5030,6 +5379,18 @@ func (in *OpenTelemetryEnvoyProxyAccessLog) DeepCopyInto(out *OpenTelemetryEnvoy (*out)[key] = val } } + if in.ResourceAttributes != nil { + in, out := &in.ResourceAttributes, &out.ResourceAttributes + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]v1.HTTPHeader, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenTelemetryEnvoyProxyAccessLog. @@ -5042,6 +5403,33 @@ func (in *OpenTelemetryEnvoyProxyAccessLog) DeepCopy() *OpenTelemetryEnvoyProxyA return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenTelemetryTracingProvider) DeepCopyInto(out *OpenTelemetryTracingProvider) { + *out = *in + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]v1.HTTPHeader, len(*in)) + copy(*out, *in) + } + if in.ResourceAttributes != nil { + in, out := &in.ResourceAttributes, &out.ResourceAttributes + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenTelemetryTracingProvider. +func (in *OpenTelemetryTracingProvider) DeepCopy() *OpenTelemetryTracingProvider { + if in == nil { + return nil + } + out := new(OpenTelemetryTracingProvider) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Operation) DeepCopyInto(out *Operation) { *out = *in @@ -5116,6 +5504,11 @@ func (in *PassiveHealthCheck) DeepCopyInto(out *PassiveHealthCheck) { *out = new(int32) **out = **in } + if in.FailurePercentageThreshold != nil { + in, out := &in.FailurePercentageThreshold, &out.FailurePercentageThreshold + *out = new(uint32) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PassiveHealthCheck. @@ -5128,6 +5521,31 @@ func (in *PassiveHealthCheck) DeepCopy() *PassiveHealthCheck { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PathMatch) DeepCopyInto(out *PathMatch) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(v1.PathMatchType) + **out = **in + } + if in.Invert != nil { + in, out := &in.Invert, &out.Invert + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PathMatch. +func (in *PathMatch) DeepCopy() *PathMatch { + if in == nil { + return nil + } + out := new(PathMatch) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PathSettings) DeepCopyInto(out *PathSettings) { *out = *in @@ -5203,12 +5621,12 @@ func (in *PolicyTargetReferences) DeepCopyInto(out *PolicyTargetReferences) { *out = *in if in.TargetRef != nil { in, out := &in.TargetRef, &out.TargetRef - *out = new(v1alpha2.LocalPolicyTargetReferenceWithSectionName) + *out = new(v1.LocalPolicyTargetReferenceWithSectionName) (*in).DeepCopyInto(*out) } if in.TargetRefs != nil { in, out := &in.TargetRefs, &out.TargetRefs - *out = make([]v1alpha2.LocalPolicyTargetReferenceWithSectionName, len(*in)) + *out = make([]v1.LocalPolicyTargetReferenceWithSectionName, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -5232,6 +5650,31 @@ func (in *PolicyTargetReferences) DeepCopy() *PolicyTargetReferences { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PreconnectPolicy) DeepCopyInto(out *PreconnectPolicy) { + *out = *in + if in.PerEndpointPercent != nil { + in, out := &in.PerEndpointPercent, &out.PerEndpointPercent + *out = new(uint32) + **out = **in + } + if in.PredictivePercent != nil { + in, out := &in.PredictivePercent, &out.PredictivePercent + *out = new(uint32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreconnectPolicy. +func (in *PreconnectPolicy) DeepCopy() *PreconnectPolicy { + if in == nil { + return nil + } + out := new(PreconnectPolicy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PreferLocalZone) DeepCopyInto(out *PreferLocalZone) { *out = *in @@ -5282,6 +5725,11 @@ func (in *Principal) DeepCopyInto(out *Principal) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.SourceCIDRs != nil { + in, out := &in.SourceCIDRs, &out.SourceCIDRs + *out = make([]CIDR, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Principal. @@ -5369,6 +5817,11 @@ func (in *ProxyAccessLog) DeepCopy() *ProxyAccessLog { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProxyAccessLogFormat) DeepCopyInto(out *ProxyAccessLogFormat) { *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(ProxyAccessLogFormatType) + **out = **in + } if in.Text != nil { in, out := &in.Text, &out.Text *out = new(string) @@ -5597,6 +6050,28 @@ func (in *ProxyOpenTelemetrySink) DeepCopyInto(out *ProxyOpenTelemetrySink) { *out = new(string) **out = **in } + if in.ReportCountersAsDeltas != nil { + in, out := &in.ReportCountersAsDeltas, &out.ReportCountersAsDeltas + *out = new(bool) + **out = **in + } + if in.ReportHistogramsAsDeltas != nil { + in, out := &in.ReportHistogramsAsDeltas, &out.ReportHistogramsAsDeltas + *out = new(bool) + **out = **in + } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]v1.HTTPHeader, len(*in)) + copy(*out, *in) + } + if in.ResourceAttributes != nil { + in, out := &in.ResourceAttributes, &out.ResourceAttributes + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyOpenTelemetrySink. @@ -5682,6 +6157,11 @@ func (in *ProxyTelemetry) DeepCopyInto(out *ProxyTelemetry) { *out = new(ProxyMetrics) (*in).DeepCopyInto(*out) } + if in.RequestID != nil { + in, out := &in.RequestID, &out.RequestID + *out = new(RequestIDSettings) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyTelemetry. @@ -5697,23 +6177,12 @@ func (in *ProxyTelemetry) DeepCopy() *ProxyTelemetry { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProxyTracing) DeepCopyInto(out *ProxyTracing) { *out = *in + in.Tracing.DeepCopyInto(&out.Tracing) if in.SamplingRate != nil { in, out := &in.SamplingRate, &out.SamplingRate *out = new(uint32) **out = **in } - if in.SamplingFraction != nil { - in, out := &in.SamplingFraction, &out.SamplingFraction - *out = new(v1.Fraction) - (*in).DeepCopyInto(*out) - } - if in.CustomTags != nil { - in, out := &in.CustomTags, &out.CustomTags - *out = make(map[string]CustomTag, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() - } - } in.Provider.DeepCopyInto(&out.Provider) } @@ -5727,6 +6196,51 @@ func (in *ProxyTracing) DeepCopy() *ProxyTracing { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *QueryParam) DeepCopyInto(out *QueryParam) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QueryParam. +func (in *QueryParam) DeepCopy() *QueryParam { + if in == nil { + return nil + } + out := new(QueryParam) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *QueryParamMatch) DeepCopyInto(out *QueryParamMatch) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(QueryParamMatchType) + **out = **in + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(string) + **out = **in + } + if in.Invert != nil { + in, out := &in.Invert, &out.Invert + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QueryParamMatch. +func (in *QueryParamMatch) DeepCopy() *QueryParamMatch { + if in == nil { + return nil + } + out := new(QueryParamMatch) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RateLimit) DeepCopyInto(out *RateLimit) { *out = *in @@ -5914,6 +6428,11 @@ func (in *RateLimitRule) DeepCopyInto(out *RateLimitRule) { *out = new(bool) **out = **in } + if in.ShadowMode != nil { + in, out := &in.ShadowMode, &out.ShadowMode + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitRule. @@ -5936,11 +6455,30 @@ func (in *RateLimitSelectCondition) DeepCopyInto(out *RateLimitSelectCondition) (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Methods != nil { + in, out := &in.Methods, &out.Methods + *out = make([]MethodMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(PathMatch) + (*in).DeepCopyInto(*out) + } if in.SourceCIDR != nil { in, out := &in.SourceCIDR, &out.SourceCIDR *out = new(SourceMatch) (*in).DeepCopyInto(*out) } + if in.QueryParams != nil { + in, out := &in.QueryParams, &out.QueryParams + *out = make([]QueryParamMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitSelectCondition. @@ -5956,6 +6494,11 @@ func (in *RateLimitSelectCondition) DeepCopy() *RateLimitSelectCondition { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RateLimitSpec) DeepCopyInto(out *RateLimitSpec) { *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(RateLimitType) + **out = **in + } if in.Global != nil { in, out := &in.Global, &out.Global *out = new(GlobalRateLimit) @@ -6155,6 +6698,26 @@ func (in *RequestHeaderCustomTag) DeepCopy() *RequestHeaderCustomTag { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RequestIDSettings) DeepCopyInto(out *RequestIDSettings) { + *out = *in + if in.Tracing != nil { + in, out := &in.Tracing, &out.Tracing + *out = new(RequestIDExtensionAction) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestIDSettings. +func (in *RequestIDSettings) DeepCopy() *RequestIDSettings { + if in == nil { + return nil + } + out := new(RequestIDSettings) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResponseOverride) DeepCopyInto(out *ResponseOverride) { *out = *in @@ -6905,6 +7468,18 @@ func (in *Tracing) DeepCopyInto(out *Tracing) { (*out)[key] = *val.DeepCopy() } } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SpanName != nil { + in, out := &in.SpanName, &out.SpanName + *out = new(TracingSpanName) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Tracing. @@ -6936,6 +7511,11 @@ func (in *TracingProvider) DeepCopyInto(out *TracingProvider) { *out = new(ZipkinTracingProvider) (*in).DeepCopyInto(*out) } + if in.OpenTelemetry != nil { + in, out := &in.OpenTelemetry, &out.OpenTelemetry + *out = new(OpenTelemetryTracingProvider) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TracingProvider. @@ -6948,6 +7528,21 @@ func (in *TracingProvider) DeepCopy() *TracingProvider { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TracingSpanName) DeepCopyInto(out *TracingSpanName) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TracingSpanName. +func (in *TracingSpanName) DeepCopy() *TracingSpanName { + if in == nil { + return nil + } + out := new(TracingSpanName) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TranslationConfig) DeepCopyInto(out *TranslationConfig) { *out = *in @@ -7274,3 +7869,18 @@ func (in *ZoneAware) DeepCopy() *ZoneAware { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ZstdCompressor) DeepCopyInto(out *ZstdCompressor) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZstdCompressor. +func (in *ZstdCompressor) DeepCopy() *ZstdCompressor { + if in == nil { + return nil + } + out := new(ZstdCompressor) + in.DeepCopyInto(out) + return out +} diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index 93aa9b575b..c3ce89ab16 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -955,9 +955,14 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index c2acc3aa8c..9cdb832634 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -993,9 +993,14 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml index 91c32bbb4e..271617e058 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -12088,9 +12088,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are + not allowed in weightedZones. + rule: '!has(self.weightedZones) + || self.weightedZones.all(z, self.weightedZones.exists_one(z2, + z2.zone == z.zone))' required: - type type: object @@ -13391,9 +13398,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are + not allowed in weightedZones. + rule: '!has(self.weightedZones) + || self.weightedZones.all(z, self.weightedZones.exists_one(z2, + z2.zone == z.zone))' required: - type type: object @@ -14842,9 +14856,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not + allowed in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone + == z.zone))' required: - type type: object @@ -16211,9 +16232,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed + in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone + == z.zone))' required: - type type: object diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml index 946867f99b..4ce25937eb 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1617,9 +1617,15 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in + weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -2805,9 +2811,15 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in + weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -4208,9 +4220,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed + in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone + == z.zone))' required: - type type: object @@ -5660,9 +5679,15 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in + weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index 9e8742e632..26b9e6ee81 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -954,9 +954,14 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 267cc185ab..3826868717 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -992,9 +992,14 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml index de76a962f6..f10f489c58 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -12087,9 +12087,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are + not allowed in weightedZones. + rule: '!has(self.weightedZones) + || self.weightedZones.all(z, self.weightedZones.exists_one(z2, + z2.zone == z.zone))' required: - type type: object @@ -13390,9 +13397,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are + not allowed in weightedZones. + rule: '!has(self.weightedZones) + || self.weightedZones.all(z, self.weightedZones.exists_one(z2, + z2.zone == z.zone))' required: - type type: object @@ -14841,9 +14855,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not + allowed in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone + == z.zone))' required: - type type: object @@ -16210,9 +16231,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed + in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone + == z.zone))' required: - type type: object diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index 118a8f28f5..a9ca3553b3 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1616,9 +1616,15 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in + weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -2804,9 +2810,15 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in + weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -4207,9 +4219,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed + in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone + == z.zone))' required: - type type: object @@ -5659,9 +5678,15 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in + weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/internal/xds/translator/cluster_test.go b/internal/xds/translator/cluster_test.go index 98a06a6b34..119a44911a 100644 --- a/internal/xds/translator/cluster_test.go +++ b/internal/xds/translator/cluster_test.go @@ -60,7 +60,7 @@ func TestBuildXdsClusterLoadAssignment(t *testing.T) { Endpoints: []*ir.DestinationEndpoint{{Host: envoyGatewayXdsServerHost, Port: bootstrap.DefaultXdsServerPort}}, } settings := []*ir.DestinationSetting{ds} - dynamicXdsClusterLoadAssignment := buildXdsClusterLoadAssignment(bootstrapXdsCluster.Name, settings, nil, nil) + dynamicXdsClusterLoadAssignment := buildXdsClusterLoadAssignment(bootstrapXdsCluster.Name, settings, nil, nil, nil) requireCmpNoDiff(t, bootstrapXdsCluster.LoadAssignment.Endpoints[0].LbEndpoints[0], dynamicXdsClusterLoadAssignment.Endpoints[0].LbEndpoints[0]) } @@ -112,7 +112,7 @@ func TestBuildXdsClusterLoadAssignmentWithHealthCheckConfig(t *testing.T) { Endpoints: []*ir.DestinationEndpoint{{Host: envoyGatewayXdsServerHost, Port: 8080}}, }} - clusterLoadAssignment := buildXdsClusterLoadAssignment("test-cluster", settings, tc.healthCheck, nil) + clusterLoadAssignment := buildXdsClusterLoadAssignment("test-cluster", settings, tc.healthCheck, nil, nil) require.Len(t, clusterLoadAssignment.GetEndpoints(), 1) require.Len(t, clusterLoadAssignment.GetEndpoints()[0].GetLbEndpoints(), 1) diff --git a/release-notes/current.yaml b/release-notes/current.yaml index ee257107d7..f87ab169f1 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -9,7 +9,7 @@ security updates: | # New features or capabilities added in this release. new features: | Added support for configuring optional health check configuration. - Support for configuring weights for locality zones + Support for configuring weights for locality zones. bug fixes: | Rejected ClientTrafficPolicy if invalid TLS cipher suites are configured. diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index 00e2a8932b..ac97dbe0bc 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -513,6 +513,37 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { ": ZoneAware PreferLocal and WeightedZones cannot be specified together", }, }, + { + desc: "weightedZones with duplicate zone names", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetRef: &gwapiv1.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1.LocalPolicyTargetReference{ + Group: gwapiv1.Group("gateway.networking.k8s.io"), + Kind: gwapiv1.Kind("Gateway"), + Name: gwapiv1.ObjectName("eg"), + }, + }, + }, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.RoundRobinLoadBalancerType, + ZoneAware: &egv1a1.ZoneAware{ + WeightedZones: []egv1a1.WeightedZoneConfig{ + {Zone: "us-east-1a", Weight: 70}, + {Zone: "us-east-1a", Weight: 30}, + }, + }, + }, + }, + } + }, + wantErrors: []string{ + "spec.loadBalancer.zoneAware: Invalid value:", + ": Duplicate zone names are not allowed in weightedZones.", + }, + }, { desc: "leastRequest with SlowStar is set", mutate: func(btp *egv1a1.BackendTrafficPolicy) { diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml index 848a128e23..7f09245fd0 100644 --- a/test/helm/gateway-crds-helm/all.out.yaml +++ b/test/helm/gateway-crds-helm/all.out.yaml @@ -22254,9 +22254,14 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -27230,9 +27235,14 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -41052,9 +41062,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are + not allowed in weightedZones. + rule: '!has(self.weightedZones) + || self.weightedZones.all(z, self.weightedZones.exists_one(z2, + z2.zone == z.zone))' required: - type type: object @@ -42355,9 +42372,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are + not allowed in weightedZones. + rule: '!has(self.weightedZones) + || self.weightedZones.all(z, self.weightedZones.exists_one(z2, + z2.zone == z.zone))' required: - type type: object @@ -43806,9 +43830,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not + allowed in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone + == z.zone))' required: - type type: object @@ -45175,9 +45206,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed + in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone + == z.zone))' required: - type type: object @@ -47885,9 +47923,15 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in + weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -49073,9 +49117,15 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in + weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -50476,9 +50526,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed + in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone + == z.zone))' required: - type type: object @@ -51928,9 +51985,15 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in + weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml index dac7cde7b2..916674ffb1 100644 --- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml +++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml @@ -1434,9 +1434,14 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -6410,9 +6415,14 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -20232,9 +20242,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are + not allowed in weightedZones. + rule: '!has(self.weightedZones) + || self.weightedZones.all(z, self.weightedZones.exists_one(z2, + z2.zone == z.zone))' required: - type type: object @@ -21535,9 +21552,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are + not allowed in weightedZones. + rule: '!has(self.weightedZones) + || self.weightedZones.all(z, self.weightedZones.exists_one(z2, + z2.zone == z.zone))' required: - type type: object @@ -22986,9 +23010,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not + allowed in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone + == z.zone))' required: - type type: object @@ -24355,9 +24386,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed + in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone + == z.zone))' required: - type type: object @@ -27065,9 +27103,15 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in + weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -28253,9 +28297,15 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in + weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -29656,9 +29706,16 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed + in weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone + == z.zone))' required: - type type: object @@ -31108,9 +31165,15 @@ spec: type: string required: - weight + - zone type: object type: array type: object + x-kubernetes-validations: + - message: Duplicate zone names are not allowed in + weightedZones. + rule: '!has(self.weightedZones) || self.weightedZones.all(z, + self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object From 96b24a6205d731130400925f8fc6236a76d909b5 Mon Sep 17 00:00:00 2001 From: jukie <10012479+Jukie@users.noreply.github.com> Date: Sun, 8 Feb 2026 16:20:47 -0700 Subject: [PATCH 10/13] CEL rule Signed-off-by: jukie <10012479+Jukie@users.noreply.github.com> --- api/v1alpha1/loadbalancer_types.go | 4 +- ....envoyproxy.io_backendtrafficpolicies.yaml | 7 +- ....envoyproxy.io_envoyextensionpolicies.yaml | 7 +- .../gateway.envoyproxy.io_envoyproxies.yaml | 36 +++----- ...ateway.envoyproxy.io_securitypolicies.yaml | 33 +++----- ....envoyproxy.io_backendtrafficpolicies.yaml | 7 +- ....envoyproxy.io_envoyextensionpolicies.yaml | 7 +- .../gateway.envoyproxy.io_envoyproxies.yaml | 36 +++----- ...ateway.envoyproxy.io_securitypolicies.yaml | 33 +++----- .../backendtrafficpolicy_test.go | 3 +- test/helm/gateway-crds-helm/all.out.yaml | 83 +++++++------------ .../envoy-gateway-crds.out.yaml | 83 +++++++------------ 12 files changed, 123 insertions(+), 216 deletions(-) diff --git a/api/v1alpha1/loadbalancer_types.go b/api/v1alpha1/loadbalancer_types.go index d2b343b588..728a4c8f07 100644 --- a/api/v1alpha1/loadbalancer_types.go +++ b/api/v1alpha1/loadbalancer_types.go @@ -180,8 +180,6 @@ type SlowStart struct { } // ZoneAware defines the configuration related to the distribution of requests between locality zones. -// -// +kubebuilder:validation:XValidation:rule="!has(self.weightedZones) || self.weightedZones.all(z, self.weightedZones.exists_one(z2, z2.zone == z.zone))",message="Duplicate zone names are not allowed in weightedZones." type ZoneAware struct { // PreferLocalZone configures zone-aware routing to prefer sending traffic to the local locality zone. // @@ -192,6 +190,8 @@ type ZoneAware struct { // Traffic is distributed proportionally based on the sum of all zone weights. // // +optional + // +listType=map + // +listMapKey=zone WeightedZones []WeightedZoneConfig `json:"weightedZones,omitempty"` } diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index c3ce89ab16..df30c57ec1 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -958,11 +958,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 9cdb832634..da2d4e856a 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -996,11 +996,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml index 271617e058..28170a9016 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -12091,13 +12091,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are - not allowed in weightedZones. - rule: '!has(self.weightedZones) - || self.weightedZones.all(z, self.weightedZones.exists_one(z2, - z2.zone == z.zone))' required: - type type: object @@ -13401,13 +13398,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are - not allowed in weightedZones. - rule: '!has(self.weightedZones) - || self.weightedZones.all(z, self.weightedZones.exists_one(z2, - z2.zone == z.zone))' required: - type type: object @@ -14859,13 +14853,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not - allowed in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone - == z.zone))' required: - type type: object @@ -16235,13 +16226,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed - in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone - == z.zone))' required: - type type: object diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml index 4ce25937eb..fc4088dc2d 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1620,12 +1620,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in - weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -2814,12 +2812,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in - weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -4223,13 +4219,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed - in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone - == z.zone))' required: - type type: object @@ -5682,12 +5675,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in - weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index 26b9e6ee81..596b036891 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -957,11 +957,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 3826868717..b255bd38d9 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -995,11 +995,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml index f10f489c58..4abd81e090 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -12090,13 +12090,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are - not allowed in weightedZones. - rule: '!has(self.weightedZones) - || self.weightedZones.all(z, self.weightedZones.exists_one(z2, - z2.zone == z.zone))' required: - type type: object @@ -13400,13 +13397,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are - not allowed in weightedZones. - rule: '!has(self.weightedZones) - || self.weightedZones.all(z, self.weightedZones.exists_one(z2, - z2.zone == z.zone))' required: - type type: object @@ -14858,13 +14852,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not - allowed in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone - == z.zone))' required: - type type: object @@ -16234,13 +16225,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed - in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone - == z.zone))' required: - type type: object diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index a9ca3553b3..6e82fdf6d6 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1619,12 +1619,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in - weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -2813,12 +2811,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in - weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -4222,13 +4218,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed - in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone - == z.zone))' required: - type type: object @@ -5681,12 +5674,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in - weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index ac97dbe0bc..812d27b83c 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -540,8 +540,7 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { } }, wantErrors: []string{ - "spec.loadBalancer.zoneAware: Invalid value:", - ": Duplicate zone names are not allowed in weightedZones.", + "spec.loadBalancer.zoneAware.weightedZones[1]: Duplicate value:", }, }, { diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml index 7f09245fd0..aae7cf23d9 100644 --- a/test/helm/gateway-crds-helm/all.out.yaml +++ b/test/helm/gateway-crds-helm/all.out.yaml @@ -22257,11 +22257,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -27238,11 +27237,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -41065,13 +41063,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are - not allowed in weightedZones. - rule: '!has(self.weightedZones) - || self.weightedZones.all(z, self.weightedZones.exists_one(z2, - z2.zone == z.zone))' required: - type type: object @@ -42375,13 +42370,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are - not allowed in weightedZones. - rule: '!has(self.weightedZones) - || self.weightedZones.all(z, self.weightedZones.exists_one(z2, - z2.zone == z.zone))' required: - type type: object @@ -43833,13 +43825,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not - allowed in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone - == z.zone))' required: - type type: object @@ -45209,13 +45198,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed - in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone - == z.zone))' required: - type type: object @@ -47926,12 +47912,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in - weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -49120,12 +49104,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in - weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -50529,13 +50511,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed - in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone - == z.zone))' required: - type type: object @@ -51988,12 +51967,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in - weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml index 916674ffb1..dae1df8c55 100644 --- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml +++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml @@ -1437,11 +1437,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -6418,11 +6417,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -20245,13 +20243,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are - not allowed in weightedZones. - rule: '!has(self.weightedZones) - || self.weightedZones.all(z, self.weightedZones.exists_one(z2, - z2.zone == z.zone))' required: - type type: object @@ -21555,13 +21550,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are - not allowed in weightedZones. - rule: '!has(self.weightedZones) - || self.weightedZones.all(z, self.weightedZones.exists_one(z2, - z2.zone == z.zone))' required: - type type: object @@ -23013,13 +23005,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not - allowed in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone - == z.zone))' required: - type type: object @@ -24389,13 +24378,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed - in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone - == z.zone))' required: - type type: object @@ -27106,12 +27092,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in - weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -28300,12 +28284,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in - weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object @@ -29709,13 +29691,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed - in weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone - == z.zone))' required: - type type: object @@ -31168,12 +31147,10 @@ spec: - zone type: object type: array + x-kubernetes-list-map-keys: + - zone + x-kubernetes-list-type: map type: object - x-kubernetes-validations: - - message: Duplicate zone names are not allowed in - weightedZones. - rule: '!has(self.weightedZones) || self.weightedZones.all(z, - self.weightedZones.exists_one(z2, z2.zone == z.zone))' required: - type type: object From 7b191fe0c1fb284b9a8499fe887fb2d6c5aad88b Mon Sep 17 00:00:00 2001 From: jukie <10012479+Jukie@users.noreply.github.com> Date: Sun, 8 Feb 2026 16:28:56 -0700 Subject: [PATCH 11/13] testdata Signed-off-by: jukie <10012479+Jukie@users.noreply.github.com> --- ...dtrafficpolicy-with-weighted-zones.in.yaml | 56 +++++ ...trafficpolicy-with-weighted-zones.out.yaml | 231 ++++++++++++++++++ 2 files changed, 287 insertions(+) create mode 100644 internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.in.yaml create mode 100644 internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.out.yaml diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.in.yaml new file mode 100644 index 0000000000..43a3911ed7 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.in.yaml @@ -0,0 +1,56 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: default + name: policy-for-route + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + loadBalancer: + type: RoundRobin + zoneAware: + weightedZones: + - zone: us-east-1a + weight: 70 + - zone: us-east-1b + weight: 20 + - zone: us-west-2a + weight: 10 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.out.yaml new file mode 100644 index 0000000000..5ff3e66004 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.out.yaml @@ -0,0 +1,231 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + name: policy-for-route + namespace: default + spec: + loadBalancer: + type: RoundRobin + zoneAware: + weightedZones: + - weight: 70 + zone: us-east-1a + - weight: 20 + zone: us-east-1b + - weight: 10 + zone: us-west-2a + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: spec.targetRef is deprecated, use spec.targetRefs instead + reason: DeprecatedField + status: "True" + type: Warning + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-1 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway-1 + namespace: envoy-gateway-system +xdsIR: + envoy-gateway/gateway-1: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + metadata: + kind: Service + name: service-1 + namespace: default + sectionName: "8080" + name: httproute/default/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + policies: + - kind: BackendTrafficPolicy + name: policy-for-route + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + traffic: + loadBalancer: + roundRobin: {} + weightedZones: + - weight: 70 + zone: us-east-1a + - weight: 20 + zone: us-east-1b + - weight: 10 + zone: us-west-2a + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 From fa35ab8b57bc9bd99b07a0b92f5ffa5daa4369ae Mon Sep 17 00:00:00 2001 From: jukie <10012479+jukie@users.noreply.github.com> Date: Wed, 11 Feb 2026 13:06:30 -0700 Subject: [PATCH 12/13] gen-check Signed-off-by: jukie <10012479+jukie@users.noreply.github.com> --- .../testdata/backendtrafficpolicy-with-weighted-zones.out.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.out.yaml index 5ff3e66004..462b5e4bfe 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-weighted-zones.out.yaml @@ -121,8 +121,7 @@ infraIR: envoy-gateway/gateway-1: proxy: listeners: - - address: null - name: envoy-gateway/gateway-1/http + - name: envoy-gateway/gateway-1/http ports: - containerPort: 10080 name: http-80 From 2585decd244e8354e6728455e9820803a7d0fb7a Mon Sep 17 00:00:00 2001 From: jukie <10012479+jukie@users.noreply.github.com> Date: Wed, 11 Feb 2026 17:15:07 -0700 Subject: [PATCH 13/13] Put weightedZones first Signed-off-by: jukie <10012479+jukie@users.noreply.github.com> --- internal/xds/translator/cluster.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go index d38a6ecb78..0b3be55247 100644 --- a/internal/xds/translator/cluster.go +++ b/internal/xds/translator/cluster.go @@ -788,10 +788,10 @@ func buildXdsClusterLoadAssignment(clusterName string, destSettings []*ir.Destin // limit host selection controls during retries and session affinity. // For more details see https://github.com/envoyproxy/gateway/issues/5307#issuecomment-2688767482 switch { - case ds.PreferLocal != nil || preferLocal != nil: - localities = append(localities, buildZonalLocalities(metadata, ds, hc)...) case len(weightedZones) > 0: localities = append(localities, buildWeightedZonalLocalities(metadata, ds, hc, weightedZones)...) + case ds.PreferLocal != nil || preferLocal != nil: + localities = append(localities, buildZonalLocalities(metadata, ds, hc)...) default: localities = append(localities, buildWeightedLocalities(metadata, ds, hc)) }