diff --git a/api/v1alpha1/backend_types.go b/api/v1alpha1/backend_types.go index a35cd62b6e6..9e28a341ce1 100644 --- a/api/v1alpha1/backend_types.go +++ b/api/v1alpha1/backend_types.go @@ -17,7 +17,6 @@ const ( // AppProtocolType defines various backend applications protocols supported by Envoy Gateway // // +kubebuilder:validation:Enum=gateway.envoyproxy.io/h2c;gateway.envoyproxy.io/ws;gateway.envoyproxy.io/wss -// +notImplementedHide type AppProtocolType string const ( @@ -37,7 +36,6 @@ const ( // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].reason` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` -// +notImplementedHide type Backend struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -49,22 +47,21 @@ type Backend struct { Status BackendStatus `json:"status,omitempty"` } -// BackendEndpoint describes a backend endpoint, which can be either a fully-qualified domain name, IPv4 address or unix domain socket +// BackendEndpoint describes a backend endpoint, which can be either a fully-qualified domain name, IP address or unix domain socket // corresponding to Envoy's Address: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-address // -// +kubebuilder:validation:XValidation:rule="(has(self.fqdn) || has(self.ipv4) || has(self.unix))",message="one of fqdn, ipv4 or unix must be specified" -// +kubebuilder:validation:XValidation:rule="((has(self.fqdn) && !(has(self.ipv4) || has(self.unix))) || (has(self.ipv4) && !(has(self.fqdn) || has(self.unix))) || (has(self.unix) && !(has(self.ipv4) || has(self.fqdn))))",message="only one of fqdn, ipv4 or unix can be specified" -// +notImplementedHide +// +kubebuilder:validation:XValidation:rule="(has(self.fqdn) || has(self.ip) || has(self.unix))",message="one of fqdn, ip or unix must be specified" +// +kubebuilder:validation:XValidation:rule="((has(self.fqdn) && !(has(self.ip) || has(self.unix))) || (has(self.ip) && !(has(self.fqdn) || has(self.unix))) || (has(self.unix) && !(has(self.ip) || has(self.fqdn))))",message="only one of fqdn, ip or unix can be specified" type BackendEndpoint struct { // FQDN defines a FQDN endpoint // // +optional FQDN *FQDNEndpoint `json:"fqdn,omitempty"` - // IPv4 defines an IPv4 endpoint + // IP defines an IP endpoint. Currently, only IPv4 Addresses are supported. // // +optional - IPv4 *IPv4Endpoint `json:"ipv4,omitempty"` + IP *IPEndpoint `json:"ip,omitempty"` // Unix defines the unix domain socket endpoint // @@ -72,12 +69,10 @@ type BackendEndpoint struct { Unix *UnixSocket `json:"unix,omitempty"` } -// IPv4Endpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address +// IPEndpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-socketaddress -// -// +notImplementedHide -type IPv4Endpoint struct { - // Address defines the IPv4 address of the backend endpoint. +type IPEndpoint struct { + // Address defines the IP address of the backend endpoint. // // +kubebuilder:validation:MinLength=7 // +kubebuilder:validation:MaxLength=15 @@ -93,14 +88,12 @@ type IPv4Endpoint struct { // FQDNEndpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-socketaddress -// -// +notImplementedHide type FQDNEndpoint struct { // Hostname defines the FQDN hostname of the backend endpoint. // // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 - // +kubebuilder:validation:Pattern=`^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` + // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9]))*$` Hostname string `json:"hostname"` // Port defines the port of the backend endpoint. @@ -112,16 +105,12 @@ type FQDNEndpoint struct { // UnixSocket describes TCP/UDP unix domain socket address, corresponding to Envoy's Pipe // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-pipe -// -// +notImplementedHide type UnixSocket struct { // Path defines the unix domain socket path of the backend endpoint. Path string `json:"path"` } // BackendSpec describes the desired state of BackendSpec. -// -// +notImplementedHide type BackendSpec struct { // Endpoints defines the endpoints to be used when connecting to the backend. // @@ -167,7 +156,6 @@ const ( ) // BackendStatus defines the state of Backend -// +notImplementedHide type BackendStatus struct { // Conditions describe the current conditions of the Backend. // @@ -181,7 +169,6 @@ type BackendStatus struct { // BackendList contains a list of Backend resources. // // +kubebuilder:object:root=true -// +notImplementedHide type BackendList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` diff --git a/api/v1alpha1/envoygateway_types.go b/api/v1alpha1/envoygateway_types.go index d3b7637c437..6e84d07ba7e 100644 --- a/api/v1alpha1/envoygateway_types.go +++ b/api/v1alpha1/envoygateway_types.go @@ -493,13 +493,13 @@ type ExtensionService struct { BackendEndpoint `json:",inline"` // Host define the extension service hostname. - // Deprecated: use the appropriate transport attribute instead (FQDN,IPv4,Unix) + // Deprecated: use the appropriate transport attribute instead (FQDN,IP,Unix) // // +optional Host string `json:"host,omitempty"` // Port defines the port the extension service is exposed on. - // Deprecated: use the appropriate transport attribute instead (FQDN,IPv4,Unix) + // Deprecated: use the appropriate transport attribute instead (FQDN,IP,Unix) // // +optional // +kubebuilder:validation:Minimum=0 diff --git a/api/v1alpha1/ext_proc_types.go b/api/v1alpha1/ext_proc_types.go index 85f250c6314..27be5e6318d 100644 --- a/api/v1alpha1/ext_proc_types.go +++ b/api/v1alpha1/ext_proc_types.go @@ -51,8 +51,8 @@ type ExtProc struct { // // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=1 - // +kubebuilder:validation:XValidation:message="BackendRefs only supports Service kind.",rule="self.all(f, f.kind == 'Service')" - // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="self.all(f, f.group == '')" + // +kubebuilder:validation:XValidation:message="BackendRefs only supports Service and Backend kind.",rule="self.all(f, f.kind == 'Service' || f.kind == 'Backend')" + // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core and gateway.envoyproxy.io group.",rule="self.all(f, f.group == '' || f.group == 'gateway.envoyproxy.io')" BackendRefs []BackendRef `json:"backendRefs"` // MessageTimeout is the timeout for a response to be returned from the external processor diff --git a/api/v1alpha1/validation/envoygateway_validate.go b/api/v1alpha1/validation/envoygateway_validate.go index d4f27633c6f..7851dab4fbe 100644 --- a/api/v1alpha1/validation/envoygateway_validate.go +++ b/api/v1alpha1/validation/envoygateway_validate.go @@ -86,12 +86,12 @@ func ValidateEnvoyGateway(eg *v1alpha1.EnvoyGateway) error { } switch { - case eg.ExtensionManager.Service.Host == "" && eg.ExtensionManager.Service.FQDN == nil && eg.ExtensionManager.Service.Unix == nil && eg.ExtensionManager.Service.IPv4 == nil: + case eg.ExtensionManager.Service.Host == "" && eg.ExtensionManager.Service.FQDN == nil && eg.ExtensionManager.Service.Unix == nil && eg.ExtensionManager.Service.IP == nil: return fmt.Errorf("extension service must contain a configured target") - case eg.ExtensionManager.Service.FQDN != nil && (eg.ExtensionManager.Service.IPv4 != nil || eg.ExtensionManager.Service.Unix != nil || eg.ExtensionManager.Service.Host != ""), - eg.ExtensionManager.Service.IPv4 != nil && (eg.ExtensionManager.Service.FQDN != nil || eg.ExtensionManager.Service.Unix != nil || eg.ExtensionManager.Service.Host != ""), - eg.ExtensionManager.Service.Unix != nil && (eg.ExtensionManager.Service.IPv4 != nil || eg.ExtensionManager.Service.FQDN != nil || eg.ExtensionManager.Service.Host != ""): + case eg.ExtensionManager.Service.FQDN != nil && (eg.ExtensionManager.Service.IP != nil || eg.ExtensionManager.Service.Unix != nil || eg.ExtensionManager.Service.Host != ""), + eg.ExtensionManager.Service.IP != nil && (eg.ExtensionManager.Service.FQDN != nil || eg.ExtensionManager.Service.Unix != nil || eg.ExtensionManager.Service.Host != ""), + eg.ExtensionManager.Service.Unix != nil && (eg.ExtensionManager.Service.IP != nil || eg.ExtensionManager.Service.FQDN != nil || eg.ExtensionManager.Service.Host != ""): return fmt.Errorf("only one backend target can be configured for the extension manager") diff --git a/api/v1alpha1/validation/envoygateway_validate_test.go b/api/v1alpha1/validation/envoygateway_validate_test.go index 2823e70a47c..4163ff80f80 100644 --- a/api/v1alpha1/validation/envoygateway_validate_test.go +++ b/api/v1alpha1/validation/envoygateway_validate_test.go @@ -619,7 +619,7 @@ func TestValidateEnvoyGateway(t *testing.T) { Hostname: "foo.example.com", Port: 8080, }, - IPv4: &v1alpha1.IPv4Endpoint{ + IP: &v1alpha1.IPEndpoint{ Address: "10.9.8.7", Port: 8080, }, diff --git a/api/v1alpha1/validation/envoyproxy_validate.go b/api/v1alpha1/validation/envoyproxy_validate.go index 9c8eee5731a..c33c8832bb0 100644 --- a/api/v1alpha1/validation/envoyproxy_validate.go +++ b/api/v1alpha1/validation/envoyproxy_validate.go @@ -130,7 +130,7 @@ func validateService(spec *egv1a1.EnvoyProxySpec) []error { for _, serviceLoadBalancerSourceRange := range serviceLoadBalancerSourceRanges { if ip, _, err := net.ParseCIDR(serviceLoadBalancerSourceRange); err != nil || ip.To4() == nil { - errs = append(errs, fmt.Errorf("loadBalancerSourceRange:%s is an invalid IPv4 subnet", serviceLoadBalancerSourceRange)) + errs = append(errs, fmt.Errorf("loadBalancerSourceRange:%s is an invalid IP subnet", serviceLoadBalancerSourceRange)) } } } @@ -140,7 +140,7 @@ func validateService(spec *egv1a1.EnvoyProxySpec) []error { } if ip, err := netip.ParseAddr(*serviceLoadBalancerIP); err != nil || !ip.Unmap().Is4() { - errs = append(errs, fmt.Errorf("loadBalancerIP:%s is an invalid IPv4 address", *serviceLoadBalancerIP)) + errs = append(errs, fmt.Errorf("loadBalancerIP:%s is an invalid IP address", *serviceLoadBalancerIP)) } } if patch := spec.Provider.Kubernetes.EnvoyService.Patch; patch != nil { diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 77a4b2c8b1f..b32ee512bd5 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -259,9 +259,9 @@ func (in *BackendEndpoint) DeepCopyInto(out *BackendEndpoint) { *out = new(FQDNEndpoint) **out = **in } - if in.IPv4 != nil { - in, out := &in.IPv4, &out.IPv4 - *out = new(IPv4Endpoint) + if in.IP != nil { + in, out := &in.IP, &out.IP + *out = new(IPEndpoint) **out = **in } if in.Unix != nil { @@ -2647,16 +2647,16 @@ func (in *HealthCheck) DeepCopy() *HealthCheck { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *IPv4Endpoint) DeepCopyInto(out *IPv4Endpoint) { +func (in *IPEndpoint) DeepCopyInto(out *IPEndpoint) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPv4Endpoint. -func (in *IPv4Endpoint) DeepCopy() *IPv4Endpoint { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPEndpoint. +func (in *IPEndpoint) DeepCopy() *IPEndpoint { if in == nil { return nil } - out := new(IPv4Endpoint) + out := new(IPEndpoint) in.DeepCopyInto(out) return out } diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml index cb3538d9874..8e83322e140 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml @@ -69,7 +69,7 @@ spec: to the backend. items: description: |- - BackendEndpoint describes a backend endpoint, which can be either a fully-qualified domain name, IPv4 address or unix domain socket + BackendEndpoint describes a backend endpoint, which can be either a fully-qualified domain name, IP address or unix domain socket corresponding to Envoy's Address: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-address properties: fqdn: @@ -80,7 +80,7 @@ spec: endpoint. maxLength: 253 minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9]))*$ type: string port: description: Port defines the port of the backend endpoint. @@ -92,11 +92,12 @@ spec: - hostname - port type: object - ipv4: - description: IPv4 defines an IPv4 endpoint + ip: + description: IP defines an IP endpoint. Currently, only IPv4 + Addresses are supported. properties: address: - description: Address defines the IPv4 address of the backend + description: Address defines the IP address of the backend endpoint. maxLength: 15 minLength: 7 @@ -124,12 +125,12 @@ spec: type: object type: object x-kubernetes-validations: - - message: one of fqdn, ipv4 or unix must be specified - rule: (has(self.fqdn) || has(self.ipv4) || has(self.unix)) - - message: only one of fqdn, ipv4 or unix can be specified - rule: ((has(self.fqdn) && !(has(self.ipv4) || has(self.unix))) - || (has(self.ipv4) && !(has(self.fqdn) || has(self.unix))) || - (has(self.unix) && !(has(self.ipv4) || has(self.fqdn)))) + - message: one of fqdn, ip or unix must be specified + rule: (has(self.fqdn) || has(self.ip) || has(self.unix)) + - message: only one of fqdn, ip or unix can be specified + rule: ((has(self.fqdn) && !(has(self.ip) || has(self.unix))) || + (has(self.ip) && !(has(self.fqdn) || has(self.unix))) || (has(self.unix) + && !(has(self.ip) || has(self.fqdn)))) maxItems: 4 minItems: 1 type: array 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 7f13dee07cd..041a0d9022f 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -138,10 +138,11 @@ spec: minItems: 1 type: array x-kubernetes-validations: - - message: BackendRefs only supports Service kind. - rule: self.all(f, f.kind == 'Service') - - message: BackendRefs only supports Core group. - rule: self.all(f, f.group == '') + - message: BackendRefs only supports Service and Backend kind. + rule: self.all(f, f.kind == 'Service' || f.kind == 'Backend') + - message: BackendRefs only supports Core and gateway.envoyproxy.io + group. + rule: self.all(f, f.group == '' || f.group == 'gateway.envoyproxy.io') failOpen: description: |- FailOpen defines if requests or responses that cannot be processed due to connectivity to the diff --git a/charts/gateway-helm/templates/_rbac.tpl b/charts/gateway-helm/templates/_rbac.tpl index 4cf4082a4c2..fb9304e7d89 100644 --- a/charts/gateway-helm/templates/_rbac.tpl +++ b/charts/gateway-helm/templates/_rbac.tpl @@ -70,6 +70,7 @@ resources: - backendtrafficpolicies - securitypolicies - envoyextensionpolicies +- backends verbs: - get - list @@ -85,6 +86,7 @@ resources: - backendtrafficpolicies/status - securitypolicies/status - envoyextensionpolicies/status +- backends/status verbs: - update {{- end }} diff --git a/examples/redis/redis.yaml b/examples/redis/redis.yaml index 1a6d779265d..cee4a37c559 100644 --- a/examples/redis/redis.yaml +++ b/examples/redis/redis.yaml @@ -64,6 +64,7 @@ data: controllerName: gateway.envoyproxy.io/gatewayclass-controller extensionApis: enableEnvoyPatchPolicy: true + enableBackend: true rateLimit: backend: type: Redis diff --git a/internal/cmd/egctl/translate.go b/internal/cmd/egctl/translate.go index 8975513d7a7..6afb724bc5f 100644 --- a/internal/cmd/egctl/translate.go +++ b/internal/cmd/egctl/translate.go @@ -282,6 +282,7 @@ func translateGatewayAPIToIR(resources *gatewayapi.Resources) (*gatewayapi.Trans GlobalRateLimitEnabled: true, EndpointRoutingDisabled: true, EnvoyPatchPolicyEnabled: true, + BackendEnabled: true, } // Fix the services in the resources section so that they have an IP address - this prevents nasty @@ -309,6 +310,7 @@ func translateGatewayAPIToGatewayAPI(resources *gatewayapi.Resources) (gatewayap GlobalRateLimitEnabled: true, EndpointRoutingDisabled: true, EnvoyPatchPolicyEnabled: true, + BackendEnabled: true, } gRes, _ := gTranslator.Translate(resources) // Update the status of the GatewayClass based on EnvoyProxy validation @@ -341,6 +343,7 @@ func translateGatewayAPIToXds(dnsDomain string, resourceType string, resources * GlobalRateLimitEnabled: true, EndpointRoutingDisabled: true, EnvoyPatchPolicyEnabled: true, + BackendEnabled: true, } gRes, _ := gTranslator.Translate(resources) diff --git a/internal/extension/registry/extension_manager.go b/internal/extension/registry/extension_manager.go index c6e251d67c8..f3312923400 100644 --- a/internal/extension/registry/extension_manager.go +++ b/internal/extension/registry/extension_manager.go @@ -124,8 +124,8 @@ func getExtensionServerAddress(service *v1alpha1.ExtensionService) string { switch { case service.FQDN != nil: serverAddr = fmt.Sprintf("%s:%d", service.FQDN.Hostname, service.FQDN.Port) - case service.IPv4 != nil: - serverAddr = fmt.Sprintf("%s:%d", service.IPv4.Address, service.IPv4.Port) + case service.IP != nil: + serverAddr = fmt.Sprintf("%s:%d", service.IP.Address, service.IP.Port) case service.Unix != nil: serverAddr = fmt.Sprintf("unix://%s", service.Unix.Path) case service.Host != "": diff --git a/internal/extension/registry/extension_manager_test.go b/internal/extension/registry/extension_manager_test.go index 28e7d84ffdd..38386add268 100644 --- a/internal/extension/registry/extension_manager_test.go +++ b/internal/extension/registry/extension_manager_test.go @@ -32,10 +32,10 @@ func TestGetExtensionServerAddress(t *testing.T) { Expected: "extserver.svc.cluster.local:5050", }, { - Name: "has an IPv4", + Name: "has an IP", Service: &v1alpha1.ExtensionService{ BackendEndpoint: v1alpha1.BackendEndpoint{ - IPv4: &v1alpha1.IPv4Endpoint{ + IP: &v1alpha1.IPEndpoint{ Address: "10.10.10.10", Port: 5050, }, diff --git a/internal/gatewayapi/backend.go b/internal/gatewayapi/backend.go new file mode 100644 index 00000000000..8c9f20f69d5 --- /dev/null +++ b/internal/gatewayapi/backend.go @@ -0,0 +1,72 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package gatewayapi + +import ( + "fmt" + "net/netip" + "strings" + + "k8s.io/apimachinery/pkg/util/validation" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/gatewayapi/status" +) + +func (t *Translator) ProcessBackends(backends []*egv1a1.Backend) []*egv1a1.Backend { + var res []*egv1a1.Backend + for _, backend := range backends { + backend := backend.DeepCopy() + + // Ensure Backends are enabled + if !t.BackendEnabled { + status.UpdateBackendStatusAcceptedCondition(backend, false, + "The Backend was not accepted since Backend is not enabled in Envoy Gateway Config") + } else { + if err := validateBackend(backend); err != nil { + status.UpdateBackendStatusAcceptedCondition(backend, false, fmt.Sprintf("The Backend was not accepted: %s", err.Error())) + } else { + status.UpdateBackendStatusAcceptedCondition(backend, true, "The Backend was accepted") + } + } + + res = append(res, backend) + } + + return res +} + +func validateBackend(backend *egv1a1.Backend) error { + for _, ep := range backend.Spec.Endpoints { + if ep.FQDN != nil { + hostname := ep.FQDN.Hostname + // must be a valid hostname + if errs := validation.IsDNS1123Subdomain(hostname); errs != nil { + return fmt.Errorf("hostname %s is not a valid FQDN", hostname) + } + if len(strings.Split(hostname, ".")) < 2 { + return fmt.Errorf("hostname %s should be a domain with at least two segments separated by dots", hostname) + } + // IP addresses are not allowed so parsing the hostname as an address needs to fail + if _, err := netip.ParseAddr(hostname); err == nil { + return fmt.Errorf("hostname %s is an IP address", hostname) + } + } else if ep.IP != nil { + ip, err := netip.ParseAddr(ep.IP.Address) + if err != nil { + return fmt.Errorf("IP address %s is invalid", ep.IP.Address) + } else { + if !ip.Is4() { + return fmt.Errorf("IP address %s is not IPv4", ep.IP.Address) + } + if ip.IsLoopback() { + return fmt.Errorf("IP address %s in the loopback range is not supported", ep.IP.Address) + } + } + } + } + return nil +} diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go index b4c89db790f..fc0f67ba2e0 100644 --- a/internal/gatewayapi/envoyextensionpolicy.go +++ b/internal/gatewayapi/envoyextensionpolicy.go @@ -439,11 +439,18 @@ func (t *Translator) buildExtProc( Settings: dsl, } - authority = fmt.Sprintf( - "%s.%s:%d", - extProc.BackendRefs[0].Name, - NamespaceDerefOr(extProc.BackendRefs[0].Namespace, policyNamespacedName.Namespace), - *extProc.BackendRefs[0].Port) + if extProc.BackendRefs[0].Port != nil { + authority = fmt.Sprintf( + "%s.%s:%d", + extProc.BackendRefs[0].Name, + NamespaceDerefOr(extProc.BackendRefs[0].Namespace, policyNamespacedName.Namespace), + *extProc.BackendRefs[0].Port) + } else { + authority = fmt.Sprintf( + "%s.%s", + extProc.BackendRefs[0].Name, + NamespaceDerefOr(extProc.BackendRefs[0].Namespace, policyNamespacedName.Namespace)) + } extProcIR := &ir.ExtProc{ Name: name, diff --git a/internal/gatewayapi/ext_service.go b/internal/gatewayapi/ext_service.go index b813aee266b..7e773ac44c9 100644 --- a/internal/gatewayapi/ext_service.go +++ b/internal/gatewayapi/ext_service.go @@ -10,11 +10,10 @@ import ( "fmt" "strings" - v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" - egv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/ir" @@ -29,54 +28,42 @@ func (t *Translator) processExtServiceDestination( resources *Resources, ) (*ir.DestinationSetting, error) { var ( - endpoints []*ir.DestinationEndpoint - addrType *ir.DestinationAddressType - servicePort v1.ServicePort - backendTLS *ir.TLSUpstreamConfig + backendTLS *ir.TLSUpstreamConfig + ds *ir.DestinationSetting ) - serviceNamespace := NamespaceDerefOr(backendRef.Namespace, policyNamespacedName.Namespace) - service := resources.GetService(serviceNamespace, string(backendRef.Name)) - for _, port := range service.Spec.Ports { - if port.Port == int32(*backendRef.Port) { - servicePort = port - break - } - } + backendNamespace := NamespaceDerefOr(backendRef.Namespace, policyNamespacedName.Namespace) - if servicePort.AppProtocol != nil && - *servicePort.AppProtocol == "kubernetes.io/h2c" { - protocol = ir.HTTP2 + switch KindDerefOr(backendRef.Kind, KindService) { + case KindService: + ds = t.processServiceDestinationSetting(*backendRef, backendNamespace, protocol, resources) + case egv1a1.KindBackend: + if !t.BackendEnabled { + return nil, fmt.Errorf("resource %s of type Backend cannot be used since Backend is disabled in Envoy Gateway configuration", string(backendRef.Name)) + } + ds = t.processBackendDestinationSetting(*backendRef, backendNamespace, resources) + ds.Protocol = protocol } - // Route to endpoints by default - if !t.EndpointRoutingDisabled { - endpointSlices := resources.GetEndpointSlicesForBackend( - serviceNamespace, string(backendRef.Name), KindService) - endpoints, addrType = getIREndpointsFromEndpointSlices( - endpointSlices, servicePort.Name, servicePort.Protocol) - } else { - // Fall back to Service ClusterIP routing - ep := ir.NewDestEndpoint( - service.Spec.ClusterIP, - uint32(*backendRef.Port)) - endpoints = append(endpoints, ep) + if ds == nil { + return nil, errors.New( + "failed to translate external service backendRef") } // TODO: support mixed endpointslice address type for the same backendRef - if !t.EndpointRoutingDisabled && addrType != nil && *addrType == ir.MIXED { + if !t.EndpointRoutingDisabled && ds.AddressType != nil && *ds.AddressType == ir.MIXED { return nil, errors.New( "mixed endpointslice address type for the same backendRef is not supported") } backendTLS = t.applyBackendTLSSetting( *backendRef, - serviceNamespace, + backendNamespace, // Gateway is not the appropriate parent reference here because the owner // of the BackendRef is the policy, and there is no hierarchy // relationship between the policy and a gateway. // The owner policy of the BackendRef is used as the parent reference here. - egv1a2.ParentReference{ + gwapiv1a2.ParentReference{ Group: ptr.To(gwapiv1.Group(egv1a1.GroupName)), Kind: ptr.To(gwapiv1.Kind(policyKind)), Namespace: ptr.To(gwapiv1.Namespace(policyNamespacedName.Namespace)), @@ -84,13 +71,12 @@ func (t *Translator) processExtServiceDestination( }, resources) - return &ir.DestinationSetting{ - Weight: ptr.To(uint32(1)), - Protocol: protocol, - Endpoints: endpoints, - AddressType: addrType, - TLS: backendTLS, - }, nil + ds.TLS = backendTLS + + // TODO: support weighted non-xRoute backends + ds.Weight = ptr.To(uint32(1)) + + return ds, nil } // TODO: also refer to extension type, as WASM may also introduce destinations diff --git a/internal/gatewayapi/resource.go b/internal/gatewayapi/resource.go index d4fe4dde67c..6f03b6267a6 100644 --- a/internal/gatewayapi/resource.go +++ b/internal/gatewayapi/resource.go @@ -57,6 +57,7 @@ type Resources struct { BackendTLSPolicies []*gwapiv1a3.BackendTLSPolicy `json:"backendTLSPolicies,omitempty" yaml:"backendTLSPolicies,omitempty"` EnvoyExtensionPolicies []*egv1a1.EnvoyExtensionPolicy `json:"envoyExtensionPolicies,omitempty" yaml:"envoyExtensionPolicies,omitempty"` ExtensionServerPolicies []unstructured.Unstructured `json:"extensionServerPolicies,omitempty" yaml:"extensionServerPolicies,omitempty"` + Backends []*egv1a1.Backend `json:"backends,omitempty" yaml:"backends,omitempty"` } func NewResources() *Resources { @@ -79,6 +80,7 @@ func NewResources() *Resources { BackendTLSPolicies: []*gwapiv1a3.BackendTLSPolicy{}, EnvoyExtensionPolicies: []*egv1a1.EnvoyExtensionPolicy{}, ExtensionServerPolicies: []unstructured.Unstructured{}, + Backends: []*egv1a1.Backend{}, } } @@ -112,6 +114,16 @@ func (r *Resources) GetServiceImport(namespace, name string) *mcsapi.ServiceImpo return nil } +func (r *Resources) GetBackend(namespace, name string) *egv1a1.Backend { + for _, be := range r.Backends { + if be.Namespace == namespace && be.Name == name { + return be + } + } + + return nil +} + func (r *Resources) GetSecret(namespace, name string) *v1.Secret { for _, secret := range r.Secrets { if secret.Namespace == namespace && secret.Name == name { diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 6301193b903..21b0485ef8f 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -7,6 +7,7 @@ package gatewayapi import ( "fmt" + "net" "strconv" "strings" "time" @@ -19,6 +20,7 @@ import ( gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" mcsapi "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" + "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/gatewayapi/status" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/utils/regex" @@ -1191,10 +1193,24 @@ func (t *Translator) processDestination(backendRefContext BackendRefContext, }, resources) ds.Filters = t.processDestinationFilters(routeType, backendRefContext, parentRef, route, resources) + case v1alpha1.KindBackend: + ds = t.processBackendDestinationSetting(backendRef.BackendObjectReference, backendNamespace, resources) + ds.TLS = t.applyBackendTLSSetting( + backendRef.BackendObjectReference, + backendNamespace, + gwapiv1a2.ParentReference{ + Group: parentRef.Group, + Kind: parentRef.Kind, + Namespace: parentRef.Namespace, + Name: parentRef.Name, + SectionName: parentRef.SectionName, + Port: parentRef.Port, + }, + resources) + ds.Filters = t.processDestinationFilters(routeType, backendRefContext, parentRef, route, resources) } - // TODO: support mixed endpointslice address type for the same backendRef - if !t.EndpointRoutingDisabled && addrType != nil && *addrType == ir.MIXED { + if err := validateDestinationSettings(ds, t.EndpointRoutingDisabled, backendRef.Kind); err != nil { routeStatus := GetRouteStatus(route) status.SetRouteStatusCondition(routeStatus, parentRef.routeParentStatusIdx, @@ -1202,13 +1218,29 @@ func (t *Translator) processDestination(backendRefContext BackendRefContext, gwapiv1.RouteConditionResolvedRefs, metav1.ConditionFalse, gwapiv1a2.RouteReasonResolvedRefs, - "Mixed endpointslice address type for the same backendRef is not supported") + err.Error()) } ds.Weight = &weight return ds } +func validateDestinationSettings(destinationSettings *ir.DestinationSetting, endpointRoutingDisabled bool, kind *gwapiv1.Kind) error { + // TODO: support mixed endpointslice address type for the same backendRef + switch KindDerefOr(kind, KindService) { + case v1alpha1.KindBackend: + if destinationSettings.AddressType != nil && *destinationSettings.AddressType == ir.MIXED { + return fmt.Errorf("mixed FQDN and IP or Unix address type for the same backendRef is not supported") + } + case KindService, KindServiceImport: + if !endpointRoutingDisabled && destinationSettings.AddressType != nil && *destinationSettings.AddressType == ir.MIXED { + return fmt.Errorf("mixed endpointslice address type for the same backendRef is not supported") + } + } + + return nil +} + func (t *Translator) processServiceDestinationSetting(backendRef gwapiv1.BackendObjectReference, backendNamespace string, protocol ir.AppProtocol, resources *Resources, ) *ir.DestinationSetting { @@ -1491,3 +1523,66 @@ func getTargetBackendReference(backendRef gwapiv1a2.BackendObjectReference) gwap } return ref } + +func (t *Translator) processBackendDestinationSetting(backendRef gwapiv1.BackendObjectReference, backendNamespace string, resources *Resources) *ir.DestinationSetting { + var ( + dstEndpoints []*ir.DestinationEndpoint + dstAddrType *ir.DestinationAddressType + dstProtocol ir.AppProtocol + ) + + addrTypeMap := make(map[ir.DestinationAddressType]int) + + backend := resources.GetBackend(backendNamespace, string(backendRef.Name)) + for _, bep := range backend.Spec.Endpoints { + var irde *ir.DestinationEndpoint + switch { + case bep.IP != nil: + ip := net.ParseIP(bep.IP.Address) + if ip != nil { + addrTypeMap[ir.IP]++ + irde = &ir.DestinationEndpoint{ + Host: bep.IP.Address, + Port: uint32(bep.IP.Port), + } + } + case bep.FQDN != nil: + addrTypeMap[ir.FQDN]++ + irde = &ir.DestinationEndpoint{ + Host: bep.FQDN.Hostname, + Port: uint32(bep.FQDN.Port), + } + case bep.Unix != nil: + addrTypeMap[ir.IP]++ + irde = &ir.DestinationEndpoint{ + Path: ptr.To(bep.Unix.Path), + } + } + + dstEndpoints = append(dstEndpoints, irde) + } + + for addrTypeState, addrTypeCounts := range addrTypeMap { + if addrTypeCounts == len(backend.Spec.Endpoints) { + dstAddrType = ptr.To(addrTypeState) + break + } + } + + if len(addrTypeMap) > 0 && dstAddrType == nil { + dstAddrType = ptr.To(ir.MIXED) + } + + for _, ap := range backend.Spec.AppProtocols { + if ap == v1alpha1.AppProtocolTypeH2C { + dstProtocol = ir.HTTP2 + break + } + } + + return &ir.DestinationSetting{ + Protocol: dstProtocol, + Endpoints: dstEndpoints, + AddressType: dstAddrType, + } +} diff --git a/internal/gatewayapi/runner/runner.go b/internal/gatewayapi/runner/runner.go index f2d407d622e..fa5d3dc11f1 100644 --- a/internal/gatewayapi/runner/runner.go +++ b/internal/gatewayapi/runner/runner.go @@ -85,6 +85,7 @@ func (r *Runner) subscribeAndTranslate(ctx context.Context) { GatewayClassName: v1.ObjectName(resources.GatewayClass.Name), GlobalRateLimitEnabled: r.EnvoyGateway.RateLimit != nil, EnvoyPatchPolicyEnabled: r.EnvoyGateway.ExtensionAPIs != nil && r.EnvoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy, + BackendEnabled: r.EnvoyGateway.ExtensionAPIs != nil && r.EnvoyGateway.ExtensionAPIs.EnableBackend, Namespace: r.Namespace, MergeGateways: gatewayapi.IsMergeGatewaysEnabled(resources), } diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index 1bc0d6c622b..0734f7a73cf 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -824,11 +824,7 @@ func (t *Translator) buildExtAuth(policy *egv1a1.SecurityPolicy, resources *Reso return nil, errors.New("one of grpc or http must be specified") } - if err = t.validateExtServiceBackendReference( - backendRef, - policy.Namespace, - KindSecurityPolicy, - resources); err != nil { + if err = t.validateExtServiceBackendReference(backendRef, policy.Namespace, policy.Kind, resources); err != nil { return nil, err } authority = fmt.Sprintf("%s.%s:%d", diff --git a/internal/gatewayapi/status/backend.go b/internal/gatewayapi/status/backend.go new file mode 100644 index 00000000000..7b841baaa8a --- /dev/null +++ b/internal/gatewayapi/status/backend.go @@ -0,0 +1,42 @@ +// 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. + +// This file contains code derived from Contour, +// https://github.com/projectcontour/contour +// from the source file +// https://github.com/projectcontour/contour/blob/main/internal/status/gatewayclassconditions.go +// and is provided here subject to the following: +// Copyright Project Contour Authors +// SPDX-License-Identifier: Apache-2.0 + +package status + +import ( + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" +) + +// UpdateBackendStatusAcceptedCondition updates the status condition for the provided Backend based on the accepted state. +func UpdateBackendStatusAcceptedCondition(be *egv1a1.Backend, accepted bool, msg string) *egv1a1.Backend { + be.Status.Conditions = MergeConditions(be.Status.Conditions, computeBackendAcceptedCondition(be, accepted, msg)) + return be +} + +// computeBackendAcceptedCondition computes the Backend Accepted status condition. +func computeBackendAcceptedCondition(be *egv1a1.Backend, accepted bool, msg string) metav1.Condition { + switch accepted { + case true: + return newCondition(string(egv1a1.BackendReasonInvalid), metav1.ConditionTrue, + string(egv1a1.BackendConditionAccepted), + "The Backend was accepted", time.Now(), be.Generation) + default: + return newCondition(string(egv1a1.BackendReasonAccepted), metav1.ConditionFalse, + string(egv1a1.BackendConditionAccepted), + msg, time.Now(), be.Generation) + } +} diff --git a/internal/gatewayapi/testdata/backend-invalid-feature-disabled.in.yaml b/internal/gatewayapi/testdata/backend-invalid-feature-disabled.in.yaml new file mode 100644 index 00000000000..af0b2aa9ec5 --- /dev/null +++ b/internal/gatewayapi/testdata/backend-invalid-feature-disabled.in.yaml @@ -0,0 +1,61 @@ +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: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/1" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 +envoyExtensionPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyExtensionPolicy + metadata: + namespace: default + name: envoy-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + extProc: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip diff --git a/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml b/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml new file mode 100755 index 00000000000..6b95feb0a07 --- /dev/null +++ b/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml @@ -0,0 +1,178 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was not accepted since Backend is not enabled in Envoy + Gateway Config + reason: Accepted + status: "False" + type: Accepted +envoyExtensionPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyExtensionPolicy + metadata: + creationTimestamp: null + name: envoy-gateway + namespace: default + spec: + extProc: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + 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: 'ExtProcs: resource backend-ip of type Backend cannot be used since + Backend is disabled in Envoy Gateway configuration.' + reason: Invalid + status: "False" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + 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: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + matches: + - path: + value: /1 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resource default/backend-ip of type Backend cannot be used since + Backend is disabled in Envoy Gateway configuration + reason: UnsupportedValue + status: "False" + 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 + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - weight: 1 + directResponse: + statusCode: 500 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /1 diff --git a/internal/gatewayapi/testdata/backend-invalid-hostname-address.in.yaml b/internal/gatewayapi/testdata/backend-invalid-hostname-address.in.yaml new file mode 100644 index 00000000000..81aca19efd8 --- /dev/null +++ b/internal/gatewayapi/testdata/backend-invalid-hostname-address.in.yaml @@ -0,0 +1,41 @@ +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: '*.foo.com' + port: 3000 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: 'localhost' + port: 3000 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn + namespace: default + spec: + endpoints: + - ip: + address: '127.0.0.3' + port: 3000 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: example.com + port: 3001 diff --git a/internal/gatewayapi/testdata/backend-invalid-hostname-address.out.yaml b/internal/gatewayapi/testdata/backend-invalid-hostname-address.out.yaml new file mode 100755 index 00000000000..e917d9cb2b8 --- /dev/null +++ b/internal/gatewayapi/testdata/backend-invalid-hostname-address.out.yaml @@ -0,0 +1,77 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: '*.foo.com' + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: 'The Backend was not accepted: hostname *.foo.com is not a valid FQDN' + reason: Accepted + status: "False" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: localhost + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: 'The Backend was not accepted: hostname localhost should be a domain + with at least two segments separated by dots' + reason: Accepted + status: "False" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn + namespace: default + spec: + endpoints: + - ip: + address: 127.0.0.3 + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: 'The Backend was not accepted: IP address 127.0.0.3 in the loopback + range is not supported' + reason: Accepted + status: "False" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: example.com + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: 'The Backend was not accepted: IP address example.com is invalid' + reason: Accepted + status: "False" + type: Accepted +infraIR: {} +xdsIR: {} diff --git a/internal/gatewayapi/testdata/backendtlspolicy-default-ns.in.yaml b/internal/gatewayapi/testdata/backendtlspolicy-default-ns.in.yaml index abc821f8eab..a92a6be6023 100644 --- a/internal/gatewayapi/testdata/backendtlspolicy-default-ns.in.yaml +++ b/internal/gatewayapi/testdata/backendtlspolicy-default-ns.in.yaml @@ -33,7 +33,10 @@ httpRoutes: - name: http-backend namespace: default port: 8080 - + - name: backend-ip-tls + namespace: default + kind: Backend + group: gateway.envoyproxy.io referenceGrants: - apiVersion: gateway.networking.k8s.io/v1alpha2 kind: ReferenceGrant @@ -54,7 +57,8 @@ referenceGrants: to: - group: "" kind: Service - + - group: gateway.envoyproxy.io + kind: Backend services: - apiVersion: v1 kind: Service @@ -133,3 +137,30 @@ backendTLSPolicies: group: "" kind: ConfigMap hostname: example.com + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-btls-backend-ip + namespace: default + spec: + targetRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls + validation: + caCertificateRefs: + - name: ca-cmap + group: '' + kind: ConfigMap + hostname: ip-backend +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip-tls + namespace: default + spec: + endpoints: + - ip: + address: 2.2.2.2 + port: 3443 diff --git a/internal/gatewayapi/testdata/backendtlspolicy-default-ns.out.yaml b/internal/gatewayapi/testdata/backendtlspolicy-default-ns.out.yaml index 1becf7daff1..71e52ee0b0d 100644 --- a/internal/gatewayapi/testdata/backendtlspolicy-default-ns.out.yaml +++ b/internal/gatewayapi/testdata/backendtlspolicy-default-ns.out.yaml @@ -30,6 +30,55 @@ backendTLSPolicies: status: "True" type: Accepted controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-btls-backend-ip + namespace: default + spec: + targetRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + name: ca-cmap + hostname: ip-backend + status: + ancestors: + - ancestorRef: + name: gateway-btls + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip-tls + namespace: default + spec: + endpoints: + - ip: + address: 2.2.2.2 + port: 3443 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid gateways: - apiVersion: gateway.networking.k8s.io/v1 kind: Gateway @@ -88,6 +137,10 @@ httpRoutes: - name: http-backend namespace: default port: 8080 + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls + namespace: default matches: - path: type: Exact @@ -156,6 +209,16 @@ xdsIR: name: policy-btls/default-ca sni: example.com weight: 1 + - addressType: IP + endpoints: + - host: 2.2.2.2 + port: 3443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls-backend-ip/default-ca + sni: ip-backend + weight: 1 hostname: '*' isHTTP2: false name: httproute/envoy-gateway/httproute-btls/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.in.yaml index 71ad79e6215..dad20362396 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.in.yaml @@ -122,6 +122,8 @@ referenceGrants: to: - group: '' kind: Service + - group: gateway.envoyproxy.io + kind: Backend configMaps: - apiVersion: v1 kind: ConfigMap @@ -167,6 +169,22 @@ backendTLSPolicies: group: '' kind: ConfigMap hostname: grpc-backend +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-btls-backend-ip + namespace: envoy-gateway + spec: + targetRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls + validation: + caCertificateRefs: + - name: ca-cmap + group: '' + kind: ConfigMap + hostname: ip-backend envoyExtensionPolicies: - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyExtensionPolicy @@ -185,3 +203,31 @@ envoyExtensionPolicies: Port: 8000 - Name: grpc-backend-2 Port: 9000 + - Name: backend-ip + Kind: Backend + Group: gateway.envoyproxy.io + - Name: backend-ip-tls + Namespace: envoy-gateway + Kind: Backend + Group: gateway.envoyproxy.io +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip-tls + namespace: envoy-gateway + spec: + endpoints: + - ip: + address: 2.2.2.2 + port: 3443 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml index ba95b6a27f0..dcc1e7522b1 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml @@ -31,6 +31,74 @@ backendTLSPolicies: status: "True" type: Accepted controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-btls-backend-ip + namespace: envoy-gateway + spec: + targetRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + name: ca-cmap + hostname: ip-backend + status: + ancestors: + - ancestorRef: + group: gateway.envoyproxy.io + kind: EnvoyExtensionPolicy + name: policy-for-http-route + namespace: default + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip-tls + namespace: envoy-gateway + spec: + endpoints: + - ip: + address: 2.2.2.2 + port: 3443 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid envoyExtensionPolicies: - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyExtensionPolicy @@ -46,6 +114,13 @@ envoyExtensionPolicies: port: 8000 - name: grpc-backend-2 port: 9000 + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls + namespace: envoy-gateway targetRef: group: gateway.networking.k8s.io kind: HTTPRoute @@ -243,6 +318,23 @@ xdsIR: port: 9000 protocol: GRPC weight: 1 + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 3001 + protocol: GRPC + weight: 1 + - addressType: IP + endpoints: + - host: 2.2.2.2 + port: 3443 + protocol: GRPC + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls-backend-ip/envoy-gateway-ca + sni: ip-backend + weight: 1 name: envoyextensionpolicy/default/policy-for-http-route/0 hostname: www.foo.com isHTTP2: false diff --git a/internal/gatewayapi/testdata/grpcroute-with-backend.in.yaml b/internal/gatewayapi/testdata/grpcroute-with-backend.in.yaml new file mode 100644 index 00000000000..a02496321ec --- /dev/null +++ b/internal/gatewayapi/testdata/grpcroute-with-backend.in.yaml @@ -0,0 +1,49 @@ +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 +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + namespace: default + name: grpcroute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - method: + service: com.ExampleExact + type: Exact + - method: + service: com.[A-Z]+ + type: RegularExpression + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 diff --git a/internal/gatewayapi/testdata/grpcroute-with-backend.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-backend.out.yaml new file mode 100755 index 00000000000..1227e5685d2 --- /dev/null +++ b/internal/gatewayapi/testdata/grpcroute-with-backend.out.yaml @@ -0,0 +1,161 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + 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 +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + creationTimestamp: null + name: grpcroute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + matches: + - method: + service: com.ExampleExact + type: Exact + - method: + service: com.[A-Z]+ + type: RegularExpression + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resource default/backend-ip of type Backend is not supported for + GRPCRoute routes + reason: UnsupportedValue + status: "False" + 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 + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: true + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: grpcroute/default/grpcroute-1/rule/0 + settings: + - weight: 1 + directResponse: + statusCode: 500 + hostname: '*' + isHTTP2: true + name: grpcroute/default/grpcroute-1/rule/0/match/1/* + pathMatch: + distinct: false + name: "" + safeRegex: /com.[A-Z]+/[A-Za-z_][A-Za-z_0-9]* + - destination: + name: grpcroute/default/grpcroute-1/rule/0 + settings: + - weight: 1 + directResponse: + statusCode: 500 + hostname: '*' + isHTTP2: true + name: grpcroute/default/grpcroute-1/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /com.ExampleExact diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-and-core-backendrefs.in.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-and-core-backendrefs.in.yaml new file mode 100644 index 00000000000..d2ecaa7816a --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-and-core-backendrefs.in.yaml @@ -0,0 +1,213 @@ +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-static + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/1" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - name: service-ip + port: 8080 + - name: service-import-ip + group: multicluster.x-k8s.io + kind: ServiceImport + port: 8081 + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-fqdn + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/2" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + - name: service-fqdn + port: 8080 + - name: service-import-fqdn + group: multicluster.x-k8s.io + kind: ServiceImport + port: 8081 +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-uds + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend.sock + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 +services: + - apiVersion: v1 + kind: Service + metadata: + namespace: default + name: service-fqdn + spec: + clusterIP: 1.1.1.1 + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 + - apiVersion: v1 + kind: Service + metadata: + namespace: default + name: service-ip + spec: + clusterIP: 2.2.2.2 + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 +serviceImports: + - apiVersion: multicluster.x-k8s.io/v1alpha1 + kind: ServiceImport + metadata: + namespace: default + name: service-import-fqdn + spec: + ips: + - 7.7.7.7 + ports: + - port: 8081 + name: http + protocol: TCP + - apiVersion: multicluster.x-k8s.io/v1alpha1 + kind: ServiceImport + metadata: + namespace: default + name: service-import-ip + spec: + ips: + - 8.8.8.8 + ports: + - port: 8081 + name: http + protocol: TCP +endpointSlices: + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-service-fqdn + namespace: default + labels: + kubernetes.io/service-name: service-fqdn + addressType: FQDN + ports: + - name: http + protocol: TCP + port: 8080 + endpoints: + - addresses: + - "bar.foo" + conditions: + ready: true + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-service-ip + namespace: default + labels: + kubernetes.io/service-name: service-ip + addressType: IP + ports: + - name: http + protocol: TCP + port: 8080 + endpoints: + - addresses: + - "4.3.2.1" + conditions: + ready: true + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: service-import-fqdn + namespace: default + labels: + multicluster.kubernetes.io/service-name: service-import-fqdn + addressType: FQDN + ports: + - name: http + protocol: TCP + port: 8080 + endpoints: + - addresses: + - "foo.bar" + conditions: + ready: true + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: service-import-ip + namespace: default + labels: + multicluster.kubernetes.io/service-name: service-import-ip + addressType: IPv4 + ports: + - name: http + protocol: TCP + port: 8081 + endpoints: + - addresses: + - "1.2.3.4" + conditions: + ready: true diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-and-core-backendrefs.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-and-core-backendrefs.out.yaml new file mode 100755 index 00000000000..94073d08678 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-and-core-backendrefs.out.yaml @@ -0,0 +1,268 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-uds + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend.sock + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + 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: 2 + 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: + creationTimestamp: null + name: httproute-static + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - name: service-ip + port: 8080 + - group: multicluster.x-k8s.io + kind: ServiceImport + name: service-import-ip + port: 8081 + matches: + - path: + value: /1 + 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 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-fqdn + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + - name: service-fqdn + port: 8080 + - group: multicluster.x-k8s.io + kind: ServiceImport + name: service-import-fqdn + port: 8081 + matches: + - path: + value: /2 + 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 + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-static/rule/0 + settings: + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 3001 + weight: 1 + - addressType: IP + endpoints: + - host: 4.3.2.1 + port: 8080 + protocol: HTTP + weight: 1 + - addressType: IP + endpoints: + - host: 1.2.3.4 + port: 8081 + protocol: HTTP + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-static/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /1 + - destination: + name: httproute/default/httproute-fqdn/rule/0 + settings: + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 3000 + weight: 1 + - addressType: FQDN + endpoints: + - host: bar.foo + port: 8080 + protocol: HTTP + weight: 1 + - addressType: FQDN + endpoints: + - host: foo.bar + port: 8080 + protocol: HTTP + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-fqdn/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /2 diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.in.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.in.yaml new file mode 100644 index 00000000000..340df45fb61 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.in.yaml @@ -0,0 +1,121 @@ +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: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/1" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-uds-mixed + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-3 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/3" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-mixed-ip-fqdn + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/2" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-mixed-uds-fqdn +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip-uds-mixed + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend.sock + - ip: + address: 1.1.1.1 + port: 3001 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-mixed-ip-uds + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend.sock + - ip: + address: 1.1.1.1 + port: 3001 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-mixed-ip-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + - ip: + address: 1.1.1.1 + port: 3001 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-mixed-uds-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + - ip: + address: 1.1.1.1 + port: 3001 diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.out.yaml new file mode 100755 index 00000000000..7c15bd583aa --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.out.yaml @@ -0,0 +1,318 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip-uds-mixed + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend.sock + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-mixed-ip-uds + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend.sock + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-mixed-ip-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-mixed-uds-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + 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: 3 + 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: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-uds-mixed + matches: + - path: + value: /1 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Unix domain socket found in Backend default/backend-ip-uds-mixed + is not supported for xRoute backendRefs + reason: UnsupportedRefAddressFound + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-3 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-mixed-ip-fqdn + matches: + - path: + value: /3 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: mixed FQDN and IP or Unix address type for the same backendRef is + not supported + reason: ResolvedRefs + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-mixed-uds-fqdn + matches: + - path: + value: /2 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: mixed FQDN and IP or Unix address type for the same backendRef is + not supported + reason: ResolvedRefs + status: "False" + 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 + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - weight: 1 + directResponse: + statusCode: 500 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /1 + - destination: + name: httproute/default/httproute-3/rule/0 + settings: + - addressType: Mixed + endpoints: + - host: primary.foo.com + port: 3000 + - host: 1.1.1.1 + port: 3001 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-3/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /3 + - destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: Mixed + endpoints: + - host: primary.foo.com + port: 3000 + - host: 1.1.1.1 + port: 3001 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-2/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /2 diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.in.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.in.yaml new file mode 100644 index 00000000000..aeccfd4a899 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.in.yaml @@ -0,0 +1,156 @@ +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: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/1" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-uds + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-3 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/3" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/2" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-4 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/4" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-localhost + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-5 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/5" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn-localhost +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-uds + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend.sock + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip-localhost + namespace: default + spec: + endpoints: + - ip: + address: 127.0.0.1 + port: 3001 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn-localhost + namespace: default + spec: + endpoints: + - fqdn: + hostname: localhost + port: 3001 diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.out.yaml new file mode 100755 index 00000000000..c05c89dc883 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.out.yaml @@ -0,0 +1,425 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-uds + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend.sock + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip-localhost + namespace: default + spec: + endpoints: + - ip: + address: 127.0.0.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: 'The Backend was not accepted: IP address 127.0.0.1 in the loopback + range is not supported' + reason: Accepted + status: "False" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn-localhost + namespace: default + spec: + endpoints: + - fqdn: + hostname: localhost + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: 'The Backend was not accepted: hostname localhost should be a domain + with at least two segments separated by dots' + reason: Accepted + status: "False" + type: Accepted +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + 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: 5 + 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: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-uds + matches: + - path: + value: /1 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Unix domain socket found in Backend default/backend-uds is not supported + for xRoute backendRefs + reason: UnsupportedRefAddressFound + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-3 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + matches: + - path: + value: /3 + 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 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + matches: + - path: + value: /2 + 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 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-4 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-localhost + matches: + - path: + value: /4 + 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 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-5 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn-localhost + matches: + - path: + value: /5 + 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 + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - weight: 1 + directResponse: + statusCode: 500 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /1 + - destination: + name: httproute/default/httproute-3/rule/0 + settings: + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 3000 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-3/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /3 + - destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 3001 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-2/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /2 + - destination: + name: httproute/default/httproute-4/rule/0 + settings: + - addressType: IP + endpoints: + - host: 127.0.0.1 + port: 3001 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-4/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /4 + - destination: + name: httproute/default/httproute-5/rule/0 + settings: + - addressType: FQDN + endpoints: + - host: localhost + port: 3001 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-5/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /5 diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.in.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.in.yaml new file mode 100644 index 00000000000..1acf67d9dfe --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.in.yaml @@ -0,0 +1,133 @@ +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: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/1" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-uds + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/2" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-uds + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-3 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/3" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-3 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/4" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-uds + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-uds + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend.sock + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.out.yaml new file mode 100644 index 00000000000..ce5b2c2f580 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.out.yaml @@ -0,0 +1,366 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-uds + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend.sock + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + 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: 4 + 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: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-uds + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + matches: + - path: + value: /1 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Mixed endpointslice address type between backendRefs is not supported + reason: ResolvedRefs + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-uds + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + matches: + - path: + value: /2 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Unix domain socket found in Backend default/backend-uds is not supported + for xRoute backendRefs + reason: UnsupportedRefAddressFound + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-3 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + matches: + - path: + value: /3 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Mixed endpointslice address type between backendRefs is not supported + reason: ResolvedRefs + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-3 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-uds + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + matches: + - path: + value: /4 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Unix domain socket found in Backend default/backend-uds is not supported + for xRoute backendRefs + reason: UnsupportedRefAddressFound + status: "False" + 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 + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - weight: 1 + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 3001 + weight: 1 + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 3000 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /1 + - destination: + name: httproute/default/httproute-2/rule/0 + settings: + - weight: 1 + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 3001 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-2/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /2 + - destination: + name: httproute/default/httproute-3/rule/0 + settings: + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 3001 + weight: 1 + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 3000 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-3/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /3 + - destination: + name: httproute/default/httproute-3/rule/0 + settings: + - weight: 1 + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 3000 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-3/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /4 diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.in.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.in.yaml new file mode 100644 index 00000000000..671c19d3b2e --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.in.yaml @@ -0,0 +1,138 @@ +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: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/1" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-uds + - group: gateway.envoyproxy.io + kind: Backend + name: backend-uds2 + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/2" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip2 + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-3 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/3" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn2 +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-uds + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend.sock + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-uds2 + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend2.sock + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn2 + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary2.foo.com + port: 3000 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip2 + namespace: default + spec: + endpoints: + - ip: + address: 2.2.2.2 + port: 3001 diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.out.yaml new file mode 100755 index 00000000000..ab764497bb2 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.out.yaml @@ -0,0 +1,356 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-uds + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend.sock + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-uds2 + namespace: default + spec: + endpoints: + - unix: + path: /var/run/backend2.sock + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn2 + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary2.foo.com + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip2 + namespace: default + spec: + endpoints: + - ip: + address: 2.2.2.2 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + 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: 3 + 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: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-uds + - group: gateway.envoyproxy.io + kind: Backend + name: backend-uds2 + matches: + - path: + value: /1 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Unix domain socket found in Backend default/backend-uds2 is not supported + for xRoute backendRefs + reason: UnsupportedRefAddressFound + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip2 + matches: + - path: + value: /2 + 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 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-3 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn2 + matches: + - path: + value: /3 + 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 + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - weight: 1 + - weight: 1 + directResponse: + statusCode: 500 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /1 + - destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 3001 + weight: 1 + - addressType: IP + endpoints: + - host: 2.2.2.2 + port: 3001 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-2/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /2 + - destination: + name: httproute/default/httproute-3/rule/0 + settings: + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 3000 + weight: 1 + - addressType: FQDN + endpoints: + - host: primary2.foo.com + port: 3000 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-3/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /3 diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-mixed-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-mixed-address-type.out.yaml index cea76f60b53..314276475f2 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-mixed-address-type.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-mixed-address-type.out.yaml @@ -69,7 +69,7 @@ httpRoutes: status: "True" type: Accepted - lastTransitionTime: null - message: Mixed endpointslice address type for the same backendRef is not supported + message: mixed endpointslice address type for the same backendRef is not supported reason: ResolvedRefs status: "False" type: ResolvedRefs diff --git a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.in.yaml b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.in.yaml new file mode 100644 index 00000000000..3f4b5483d45 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.in.yaml @@ -0,0 +1,77 @@ +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: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 + - group: gateway.envoyproxy.io + kind: Backend + name: backend-mixed-ip-uds + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - matches: + - path: + value: "/" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-mixed-ip-uds + namespace: default + spec: + appProtocols: + - gateway.envoyproxy.io/h2c + endpoints: + - ip: + address: 10.244.0.28 + port: 3000 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn + namespace: default + spec: + appProtocols: + - gateway.envoyproxy.io/h2c + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 diff --git a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml new file mode 100755 index 00000000000..430f6e854ab --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml @@ -0,0 +1,225 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-mixed-ip-uds + namespace: default + spec: + appProtocols: + - gateway.envoyproxy.io/h2c + endpoints: + - ip: + address: 10.244.0.28 + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn + namespace: default + spec: + appProtocols: + - gateway.envoyproxy.io/h2c + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + 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: 2 + 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: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - name: service-1 + port: 8080 + - group: gateway.envoyproxy.io + kind: Backend + name: backend-mixed-ip-uds + 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 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + 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 +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 + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + - addressType: IP + endpoints: + - host: 10.244.0.28 + port: 3000 + protocol: HTTP2 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: / + - destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 3000 + protocol: HTTP2 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-2/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: / diff --git a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.in.yaml b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.in.yaml new file mode 100644 index 00000000000..b837c641bb1 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.in.yaml @@ -0,0 +1,75 @@ +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: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 + weight: 1 + - group: gateway.envoyproxy.io + kind: Backend + name: backend-mixed-ip-uds + weight: 2 + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - matches: + - path: + value: "/" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-mixed-ip-uds + namespace: default + spec: + endpoints: + - ip: + address: 10.244.0.28 + port: 3000 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 diff --git a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml new file mode 100755 index 00000000000..bd996c60996 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml @@ -0,0 +1,221 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-mixed-ip-uds + namespace: default + spec: + endpoints: + - ip: + address: 10.244.0.28 + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + 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: 2 + 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: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - name: service-1 + port: 8080 + weight: 1 + - group: gateway.envoyproxy.io + kind: Backend + name: backend-mixed-ip-uds + weight: 2 + 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 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + 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 +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 + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + - addressType: IP + endpoints: + - host: 10.244.0.28 + port: 3000 + weight: 2 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: / + - destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 3000 + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-2/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: / diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml index 1029946b473..7ced70ec612 100644 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml @@ -70,8 +70,8 @@ httpRoutes: type: Accepted - lastTransitionTime: null message: Group is invalid, only the core API group (specified by omitting - the group field or setting it to an empty string) and multicluster.x-k8s.io - are supported + the group field or setting it to an empty string), multicluster.x-k8s.io + and gateway.envoyproxy.io are supported reason: InvalidKind status: "False" type: ResolvedRefs diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml index 5deb6eea7f4..26d256a564b 100644 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml @@ -68,7 +68,8 @@ httpRoutes: status: "True" type: Accepted - lastTransitionTime: null - message: Kind is invalid, only Service and MCS ServiceImport are supported + message: Kind is invalid, only Service, MCS ServiceImport and Envoy Gateway + Backend are supported reason: InvalidKind status: "False" type: ResolvedRefs diff --git a/internal/gatewayapi/testdata/tcproute-with-backend.in.yaml b/internal/gatewayapi/testdata/tcproute-with-backend.in.yaml new file mode 100644 index 00000000000..667b2a3b938 --- /dev/null +++ b/internal/gatewayapi/testdata/tcproute-with-backend.in.yaml @@ -0,0 +1,41 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: tcp + protocol: TCP + port: 90 + allowedRoutes: + namespaces: + from: All +tcpRoutes: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: TCPRoute + metadata: + namespace: default + name: tcproute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 diff --git a/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml b/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml new file mode 100755 index 00000000000..c82e53e39e0 --- /dev/null +++ b/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml @@ -0,0 +1,123 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: tcp + port: 90 + protocol: TCP + 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: tcp + supportedKinds: + - group: gateway.networking.k8s.io + kind: TCPRoute +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/tcp + ports: + - containerPort: 10090 + name: tcp-90 + protocol: TCP + servicePort: 90 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +tcpRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: TCPRoute + metadata: + creationTimestamp: null + name: tcproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resource default/backend-ip of type Backend is not supported for + TCPRoute routes + reason: UnsupportedValue + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + tcp: + - address: 0.0.0.0 + name: envoy-gateway/gateway-1/tcp + port: 10090 + routes: + - destination: + name: tcproute/default/tcproute-1/rule/-1 + settings: + - weight: 1 + name: tcproute/default/tcproute-1 diff --git a/internal/gatewayapi/testdata/tlsroute-with-backend.in.yaml b/internal/gatewayapi/testdata/tlsroute-with-backend.in.yaml new file mode 100644 index 00000000000..7fb25e34902 --- /dev/null +++ b/internal/gatewayapi/testdata/tlsroute-with-backend.in.yaml @@ -0,0 +1,44 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: tls + protocol: TLS + hostname: foo.com + port: 90 + tls: + mode: Passthrough + allowedRoutes: + namespaces: + from: All +tlsRoutes: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: TLSRoute + metadata: + namespace: default + name: tlsroute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 diff --git a/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml new file mode 100755 index 00000000000..f5839c370d4 --- /dev/null +++ b/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml @@ -0,0 +1,130 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + hostname: foo.com + name: tls + port: 90 + protocol: TLS + tls: + mode: Passthrough + 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: tls + supportedKinds: + - group: gateway.networking.k8s.io + kind: TLSRoute +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/tls + ports: + - containerPort: 10090 + name: tls-90 + protocol: TLS + servicePort: 90 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +tlsRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: TLSRoute + metadata: + creationTimestamp: null + name: tlsroute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resource default/backend-ip of type Backend is not supported for + TLSRoute routes + reason: UnsupportedValue + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + tcp: + - address: 0.0.0.0 + name: envoy-gateway/gateway-1/tls + port: 10090 + routes: + - destination: + name: tlsroute/default/tlsroute-1/rule/-1 + settings: + - weight: 1 + name: tlsroute/default/tlsroute-1 + tls: + inspector: + snis: + - foo.com diff --git a/internal/gatewayapi/translator.go b/internal/gatewayapi/translator.go index 6d095daa7c0..08f0dd8a98e 100644 --- a/internal/gatewayapi/translator.go +++ b/internal/gatewayapi/translator.go @@ -95,6 +95,9 @@ type Translator struct { // feature is enabled. EnvoyPatchPolicyEnabled bool + // BackendEnabled when the Backend feature is enabled. + BackendEnabled bool + // ExtensionGroupKinds stores the group/kind for all resources // introduced by an Extension so that the translator can // store referenced resources in the IR for later use. @@ -122,6 +125,7 @@ func newTranslateResult(gateways []*GatewayContext, backendTLSPolicies []*gwapiv1a3.BackendTLSPolicy, envoyExtensionPolicies []*egv1a1.EnvoyExtensionPolicy, extPolicies []unstructured.Unstructured, + backends []*egv1a1.Backend, xdsIR XdsIRMap, infraIR InfraIRMap, ) *TranslateResult { translateResult := &TranslateResult{ @@ -155,6 +159,7 @@ func newTranslateResult(gateways []*GatewayContext, translateResult.EnvoyExtensionPolicies = append(translateResult.EnvoyExtensionPolicies, envoyExtensionPolicies...) translateResult.ExtensionServerPolicies = append(translateResult.ExtensionServerPolicies, extPolicies...) + translateResult.Backends = append(translateResult.Backends, backends...) return translateResult } @@ -182,6 +187,9 @@ func (t *Translator) Translate(resources *Resources) (*TranslateResult, error) { // Process all Addresses for all relevant Gateways. t.ProcessAddresses(gateways, xdsIR, infraIR, resources) + // process all Backends + backends := t.ProcessBackends(resources.Backends) + // Process all relevant HTTPRoutes. httpRoutes := t.ProcessHTTPRoutes(resources.HTTPRoutes, gateways, resources, xdsIR) @@ -245,7 +253,7 @@ func (t *Translator) Translate(resources *Resources) (*TranslateResult, error) { return newTranslateResult(gateways, httpRoutes, grpcRoutes, tlsRoutes, tcpRoutes, udpRoutes, clientTrafficPolicies, backendTrafficPolicies, securityPolicies, resources.BackendTLSPolicies, envoyExtensionPolicies, - extServerPolicies, xdsIR, infraIR), translateErrs + extServerPolicies, backends, xdsIR, infraIR), translateErrs } // GetRelevantGateways returns GatewayContexts, containing a copy of the original diff --git a/internal/gatewayapi/translator_test.go b/internal/gatewayapi/translator_test.go index 56f85ad5c8c..617998713e9 100644 --- a/internal/gatewayapi/translator_test.go +++ b/internal/gatewayapi/translator_test.go @@ -44,11 +44,16 @@ func TestTranslate(t *testing.T) { testCasesConfig := []struct { name string EnvoyPatchPolicyEnabled bool + BackendEnabled bool }{ { name: "envoypatchpolicy-invalid-feature-disabled", EnvoyPatchPolicyEnabled: false, }, + { + name: "backend-invalid-feature-disabled", + EnvoyPatchPolicyEnabled: false, + }, } inputFiles, err := filepath.Glob(filepath.Join("testdata", "*.in.yaml")) @@ -63,10 +68,12 @@ func TestTranslate(t *testing.T) { resources := &Resources{} mustUnmarshal(t, input, resources) envoyPatchPolicyEnabled := true + backendEnabled := true for _, config := range testCasesConfig { if config.name == strings.Split(filepath.Base(inputFile), ".")[0] { envoyPatchPolicyEnabled = config.EnvoyPatchPolicyEnabled + backendEnabled = config.BackendEnabled } } @@ -75,6 +82,7 @@ func TestTranslate(t *testing.T) { GatewayClassName: "envoy-gateway-class", GlobalRateLimitEnabled: true, EnvoyPatchPolicyEnabled: envoyPatchPolicyEnabled, + BackendEnabled: backendEnabled, Namespace: "envoy-gateway-system", MergeGateways: IsMergeGatewaysEnabled(resources), } diff --git a/internal/gatewayapi/validate.go b/internal/gatewayapi/validate.go index 1e57a60b0fb..46847d02ac2 100644 --- a/internal/gatewayapi/validate.go +++ b/internal/gatewayapi/validate.go @@ -66,12 +66,16 @@ func (t *Translator) validateBackendRef(backendRefContext BackendRefContext, par if !t.validateBackendServiceImport(backendRef, parentRef, resources, backendNamespace, route, protocol) { return false } + case egv1a1.KindBackend: + if !t.validateBackendRefBackend(backendRef, parentRef, resources, backendNamespace, route, routeKind) { + return false + } } return true } func (t *Translator) validateBackendRefGroup(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext) bool { - if backendRef.Group != nil && *backendRef.Group != "" && *backendRef.Group != GroupMultiClusterService { + if backendRef.Group != nil && *backendRef.Group != "" && *backendRef.Group != GroupMultiClusterService && *backendRef.Group != egv1a1.GroupName { routeStatus := GetRouteStatus(route) status.SetRouteStatusCondition(routeStatus, parentRef.routeParentStatusIdx, @@ -79,7 +83,7 @@ func (t *Translator) validateBackendRefGroup(backendRef *gwapiv1a2.BackendRef, p gwapiv1.RouteConditionResolvedRefs, metav1.ConditionFalse, gwapiv1.RouteReasonInvalidKind, - fmt.Sprintf("Group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) and %s are supported", GroupMultiClusterService), + fmt.Sprintf("Group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string), %s and %s are supported", GroupMultiClusterService, egv1a1.GroupName), ) return false } @@ -87,7 +91,7 @@ func (t *Translator) validateBackendRefGroup(backendRef *gwapiv1a2.BackendRef, p } func (t *Translator) validateBackendRefKind(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext) bool { - if backendRef.Kind != nil && *backendRef.Kind != KindService && *backendRef.Kind != KindServiceImport { + if backendRef.Kind != nil && *backendRef.Kind != KindService && *backendRef.Kind != KindServiceImport && *backendRef.Kind != egv1a1.KindBackend { routeStatus := GetRouteStatus(route) status.SetRouteStatusCondition(routeStatus, parentRef.routeParentStatusIdx, @@ -95,7 +99,7 @@ func (t *Translator) validateBackendRefKind(backendRef *gwapiv1a2.BackendRef, pa gwapiv1.RouteConditionResolvedRefs, metav1.ConditionFalse, gwapiv1.RouteReasonInvalidKind, - "Kind is invalid, only Service and MCS ServiceImport are supported", + "Kind is invalid, only Service, MCS ServiceImport and Envoy Gateway Backend are supported", ) return false } @@ -173,6 +177,10 @@ func (t *Translator) validateBackendNamespace(backendRef *gwapiv1a2.BackendRef, } func (t *Translator) validateBackendPort(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext) bool { + // Envoy Gateway Backends do not require a port in the backend ref + if backendRef != nil && backendRef.Kind != nil && string(*backendRef.Kind) == egv1a1.KindBackend { + return true + } if backendRef.Port == nil { routeStatus := GetRouteStatus(route) status.SetRouteStatusCondition(routeStatus, @@ -260,6 +268,70 @@ func (t *Translator) validateBackendServiceImport(backendRef *gwapiv1a2.BackendR return true } +func (t *Translator) validateBackendRefBackend(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, resources *Resources, + backendNamespace string, route RouteContext, kind gwapiv1.Kind, +) bool { + // TODO: support additional route kinds + routeStatus := GetRouteStatus(route) + + if !t.BackendEnabled { + status.SetRouteStatusCondition(routeStatus, + parentRef.routeParentStatusIdx, + route.GetGeneration(), + gwapiv1.RouteConditionResolvedRefs, + metav1.ConditionFalse, + gwapiv1.RouteReasonUnsupportedValue, + fmt.Sprintf("Resource %s/%s of type Backend cannot be used since Backend is disabled in Envoy Gateway configuration", + NamespaceDerefOr(backendRef.Namespace, route.GetNamespace()), string(backendRef.Name)), + ) + return false + } + + if kind != KindHTTPRoute { + status.SetRouteStatusCondition(routeStatus, + parentRef.routeParentStatusIdx, + route.GetGeneration(), + gwapiv1.RouteConditionResolvedRefs, + metav1.ConditionFalse, + gwapiv1.RouteReasonUnsupportedValue, + fmt.Sprintf("Resource %s/%s of type Backend is not supported for %s routes", NamespaceDerefOr(backendRef.Namespace, route.GetNamespace()), + string(backendRef.Name), kind), + ) + return false + } + + backend := resources.GetBackend(backendNamespace, string(backendRef.Name)) + if backend == nil { + status.SetRouteStatusCondition(routeStatus, + parentRef.routeParentStatusIdx, + route.GetGeneration(), + gwapiv1.RouteConditionResolvedRefs, + metav1.ConditionFalse, + gwapiv1.RouteReasonBackendNotFound, + fmt.Sprintf("Backend %s/%s not found", NamespaceDerefOr(backendRef.Namespace, route.GetNamespace()), + string(backendRef.Name)), + ) + return false + } + + for _, bep := range backend.Spec.Endpoints { + if bep.Unix != nil { + status.SetRouteStatusCondition(routeStatus, + parentRef.routeParentStatusIdx, + route.GetGeneration(), + gwapiv1.RouteConditionResolvedRefs, + metav1.ConditionFalse, + "UnsupportedRefAddressFound", + fmt.Sprintf("Unix domain socket found in Backend %s/%s is not supported for xRoute backendRefs", backendNamespace, + string(backendRef.Name)), + ) + return false + } + } + + return true +} + func (t *Translator) validateListenerConditions(listener *ListenerContext) (isReady bool) { lConditions := listener.GetConditions() if len(lConditions) == 0 { @@ -927,10 +999,10 @@ func (t *Translator) validateSecretObjectRef( // This can also be used for the other external services deployed in the cluster, // such as the external processing filter, gRPC Access Log Service, etc. // It checks: -// 1. The group is nil or empty, indicating the core API group. -// 2. The kind is Service. -// 3. The port is specified. -// 4. The service exists and the specified port is found. +// 1. The group is nil or empty, indicating the core API group, or gateway.envoyproxy.io +// 2. The kind is Service or Backend. +// 3. The port is specified for Services. +// 4. The Service or Backend exists and the specified port is found. // 5. The cross-namespace reference is permitted by the ReferenceGrants if the // namespace is different from the policy's namespace. func (t *Translator) validateExtServiceBackendReference( @@ -941,43 +1013,54 @@ func (t *Translator) validateExtServiceBackendReference( ) error { // These are sanity checks, they should never happen because the API server // should have caught them - if backendRef.Group != nil && *backendRef.Group != "" { + if backendRef.Group != nil && *backendRef.Group != "" && *backendRef.Group != egv1a1.GroupName { return errors.New( "group is invalid, only the core API group (specified by omitting" + - " the group field or setting it to an empty string) is supported") + " the group field or setting it to an empty string) and the" + + " gateway.envoyproxy.io API group are supported") } - if backendRef.Kind != nil && *backendRef.Kind != KindService { + if backendRef.Kind != nil && *backendRef.Kind != KindService && *backendRef.Kind != egv1a1.KindBackend { return errors.New("kind is invalid, only Service (specified by omitting " + - "the kind field or setting it to 'Service') is supported") + "the kind field or setting it to 'Service') and Backend are supported") } - if backendRef.Port == nil { + if backendRef.Port == nil && !(backendRef.Kind != nil && *backendRef.Kind == egv1a1.KindBackend) { return errors.New("a valid port number corresponding to a port on the Service must be specified") } - // check if the service is valid - serviceNamespace := NamespaceDerefOr(backendRef.Namespace, ownerNamespace) - service := resources.GetService(serviceNamespace, string(backendRef.Name)) - if service == nil { - return fmt.Errorf("service %s/%s not found", serviceNamespace, backendRef.Name) - } - var portFound bool - for _, port := range service.Spec.Ports { - portProtocol := port.Protocol - if port.Protocol == "" { // Default protocol is TCP - portProtocol = v1.ProtocolTCP + backendRefKind := KindDerefOr(backendRef.Kind, KindService) + switch backendRefKind { + case KindService: + // check if the service is valid + serviceNamespace := NamespaceDerefOr(backendRef.Namespace, ownerNamespace) + service := resources.GetService(serviceNamespace, string(backendRef.Name)) + if service == nil { + return fmt.Errorf("service %s/%s not found", serviceNamespace, backendRef.Name) } - // currently only HTTP and GRPC are supported, both of which are TCP - if port.Port == int32(*backendRef.Port) && portProtocol == v1.ProtocolTCP { - portFound = true - break + var portFound bool + for _, port := range service.Spec.Ports { + portProtocol := port.Protocol + if port.Protocol == "" { // Default protocol is TCP + portProtocol = v1.ProtocolTCP + } + // currently only HTTP and GRPC are supported, both of which are TCP + if port.Port == int32(*backendRef.Port) && portProtocol == v1.ProtocolTCP { + portFound = true + break + } } - } - if !portFound { - return fmt.Errorf( - "TCP Port %d not found on service %s/%s", - *backendRef.Port, serviceNamespace, string(backendRef.Name), - ) + if !portFound { + return fmt.Errorf( + "TCP Port %d not found on service %s/%s", + *backendRef.Port, serviceNamespace, string(backendRef.Name), + ) + } + case egv1a1.KindBackend: + backendNamespace := NamespaceDerefOr(backendRef.Namespace, ownerNamespace) + backend := resources.GetBackend(backendNamespace, string(backendRef.Name)) + if backend == nil { + return fmt.Errorf("backend %s/%s not found", backendNamespace, backendRef.Name) + } } // check if the cross-namespace reference is permitted @@ -991,7 +1074,7 @@ func (t *Translator) validateExtServiceBackendReference( }, crossNamespaceTo{ group: GroupDerefOr(backendRef.Group, ""), - kind: KindDerefOr(backendRef.Kind, KindService), + kind: KindDerefOr(backendRef.Kind, backendRefKind), namespace: string(*backendRef.Namespace), name: string(backendRef.Name), }, @@ -999,7 +1082,7 @@ func (t *Translator) validateExtServiceBackendReference( ) { return fmt.Errorf( "backend ref to %s %s/%s not permitted by any ReferenceGrant", - KindService, *backendRef.Namespace, backendRef.Name) + backendRefKind, *backendRef.Namespace, backendRef.Name) } } return nil diff --git a/internal/gatewayapi/zz_generated.deepcopy.go b/internal/gatewayapi/zz_generated.deepcopy.go index 358fdaefb38..a5bf8c9974f 100644 --- a/internal/gatewayapi/zz_generated.deepcopy.go +++ b/internal/gatewayapi/zz_generated.deepcopy.go @@ -257,6 +257,17 @@ func (in *Resources) DeepCopyInto(out *Resources) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Backends != nil { + in, out := &in.Backends, &out.Backends + *out = make([]*apiv1alpha1.Backend, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(apiv1alpha1.Backend) + (*in).DeepCopyInto(*out) + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 5253cc17a4b..6fec4597268 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -38,6 +38,8 @@ var ( ErrDestinationNameEmpty = errors.New("field Name must be specified") ErrDestEndpointHostInvalid = errors.New("field Address must be a valid IP or FQDN address") ErrDestEndpointPortInvalid = errors.New("field Port specified is invalid") + ErrDestEndpointUDSPortInvalid = errors.New("field Port must not be specified for Unix Domain Socket address") + ErrDestEndpointUDSHostInvalid = errors.New("field Host must not be specified for Unix Domain Socket address") ErrStringMatchConditionInvalid = errors.New("only one of the Exact, Prefix, SafeRegex or Distinct fields must be set") ErrStringMatchNameIsEmpty = errors.New("field Name must be specified") ErrDirectResponseStatusInvalid = errors.New("only HTTP status codes 100 - 599 are supported for DirectResponse") @@ -1089,21 +1091,33 @@ type DestinationEndpoint struct { Host string `json:"host" yaml:"host"` // Port on the service to forward the request to. Port uint32 `json:"port" yaml:"port"` + // Path refers to the Unix Domain Socket + Path *string `json:"path,omitempty" yaml:"path,omitempty"` } // Validate the fields within the DestinationEndpoint structure func (d DestinationEndpoint) Validate() error { var errs error - err := validation.IsDNS1123Subdomain(d.Host) - _, pErr := netip.ParseAddr(d.Host) + // unix domain socket + if d.Path != nil { + if d.Port != 0 { + errs = errors.Join(errs, ErrDestEndpointUDSPortInvalid) + } + if d.Host != "" { + errs = errors.Join(errs, ErrDestEndpointUDSHostInvalid) + } + } else { // IP or FQDN + err := validation.IsDNS1123Subdomain(d.Host) + _, pErr := netip.ParseAddr(d.Host) - if err != nil && pErr != nil { - errs = errors.Join(errs, ErrDestEndpointHostInvalid) - } + if err != nil && pErr != nil { + errs = errors.Join(errs, ErrDestEndpointHostInvalid) + } - if d.Port == 0 { - errs = errors.Join(errs, ErrDestEndpointPortInvalid) + if d.Port == 0 { + errs = errors.Join(errs, ErrDestEndpointPortInvalid) + } } return errs diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index 591a89b4889..c760c66055a 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -450,6 +450,11 @@ func (in *ConsistentHash) DeepCopy() *ConsistentHash { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DestinationEndpoint) DeepCopyInto(out *DestinationEndpoint) { *out = *in + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationEndpoint. @@ -512,7 +517,7 @@ func (in *DestinationSetting) DeepCopyInto(out *DestinationSetting) { if (*in)[i] != nil { in, out := &(*in)[i], &(*out)[i] *out = new(DestinationEndpoint) - **out = **in + (*in).DeepCopyInto(*out) } } } diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index 202a5ea1f2e..71f3f2f701f 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -245,6 +245,10 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques } } + if err = r.processBackends(ctx, gwcResource); err != nil { + return reconcile.Result{}, err + } + // Add the referenced services, ServiceImports, and EndpointSlices in // the collected BackendRefs to the resourceTree. // BackendRefs are referred by various Route objects and the ExtAuth in SecurityPolicies. @@ -363,6 +367,7 @@ func (r *gatewayAPIReconciler) managedGatewayClasses(ctx context.Context) ([]*gw // - Services // - ServiceImports // - EndpointSlices +// - Backends func (r *gatewayAPIReconciler) processBackendRefs(ctx context.Context, gwcResource *gatewayapi.Resources, resourceMappings *resourceMappings) { for backendRef := range resourceMappings.allAssociatedBackendRefs { backendRefKind := gatewayapi.KindDerefOr(backendRef.Kind, gatewayapi.KindService) @@ -398,25 +403,40 @@ func (r *gatewayAPIReconciler) processBackendRefs(ctx context.Context, gwcResour "name", string(backendRef.Name)) } endpointSliceLabelKey = mcsapi.LabelServiceName - } - // Retrieve the EndpointSlices associated with the service - endpointSliceList := new(discoveryv1.EndpointSliceList) - opts := []client.ListOption{ - client.MatchingLabels(map[string]string{ - endpointSliceLabelKey: string(backendRef.Name), - }), - client.InNamespace(string(*backendRef.Namespace)), + case egv1a1.KindBackend: + backend := new(egv1a1.Backend) + err := r.client.Get(ctx, types.NamespacedName{Namespace: string(*backendRef.Namespace), Name: string(backendRef.Name)}, backend) + if err != nil { + r.log.Error(err, "failed to get Backend", "namespace", string(*backendRef.Namespace), + "name", string(backendRef.Name)) + } else { + resourceMappings.allAssociatedNamespaces[backend.Namespace] = struct{}{} + gwcResource.Backends = append(gwcResource.Backends, backend) + r.log.Info("added Backend to resource tree", "namespace", string(*backendRef.Namespace), + "name", string(backendRef.Name)) + } } - if err := r.client.List(ctx, endpointSliceList, opts...); err != nil { - r.log.Error(err, "failed to get EndpointSlices", "namespace", string(*backendRef.Namespace), - backendRefKind, string(backendRef.Name)) - } else { - for _, endpointSlice := range endpointSliceList.Items { - endpointSlice := endpointSlice - r.log.Info("added EndpointSlice to resource tree", "namespace", endpointSlice.Namespace, - "name", endpointSlice.Name) - gwcResource.EndpointSlices = append(gwcResource.EndpointSlices, &endpointSlice) + + // Retrieve the EndpointSlices associated with the Service and ServiceImport + if endpointSliceLabelKey != "" { + endpointSliceList := new(discoveryv1.EndpointSliceList) + opts := []client.ListOption{ + client.MatchingLabels(map[string]string{ + endpointSliceLabelKey: string(backendRef.Name), + }), + client.InNamespace(string(*backendRef.Namespace)), + } + if err := r.client.List(ctx, endpointSliceList, opts...); err != nil { + r.log.Error(err, "failed to get EndpointSlices", "namespace", string(*backendRef.Namespace), + backendRefKind, string(backendRef.Name)) + } else { + for _, endpointSlice := range endpointSliceList.Items { + endpointSlice := endpointSlice + r.log.Info("added EndpointSlice to resource tree", "namespace", endpointSlice.Namespace, + "name", endpointSlice.Name) + gwcResource.EndpointSlices = append(gwcResource.EndpointSlices, &endpointSlice) + } } } } @@ -946,6 +966,24 @@ func (r *gatewayAPIReconciler) processBackendTLSPolicies( return nil } +// processBackends adds Backends to the resourceTree +func (r *gatewayAPIReconciler) processBackends(ctx context.Context, resourceTree *gatewayapi.Resources) error { + backends := egv1a1.BackendList{} + if err := r.client.List(ctx, &backends); err != nil { + return fmt.Errorf("error listing Backends: %w", err) + } + + for _, backend := range backends.Items { + backend := backend + // Discard Status to reduce memory consumption in watchable + // It will be recomputed by the gateway-api layer + backend.Status = egv1a1.BackendStatus{} + + resourceTree.Backends = append(resourceTree.Backends, &backend) + } + return nil +} + // removeFinalizer removes the gatewayclass finalizer from the provided gc, if it exists. func (r *gatewayAPIReconciler) removeFinalizer(ctx context.Context, gc *gwapiv1.GatewayClass) error { if slice.ContainsString(gc.Finalizers, gatewayClassFinalizer) { @@ -1202,6 +1240,29 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M return err } + // Watch Backend CRUDs and process affected *Route objects. + if r.envoyGateway.ExtensionAPIs != nil && r.envoyGateway.ExtensionAPIs.EnableBackend { + backendPredicates := []predicate.TypedPredicate[*egv1a1.Backend]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.Backend]{}, + predicate.NewTypedPredicateFuncs[*egv1a1.Backend](func(be *egv1a1.Backend) bool { + return r.validateBackendForReconcile(be) + }), + } + if r.namespaceLabel != nil { + backendPredicates = append(backendPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.Backend](func(be *egv1a1.Backend) bool { + return r.hasMatchingNamespaceLabels(be) + })) + } + if err := c.Watch( + source.Kind(mgr.GetCache(), &egv1a1.Backend{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, be *egv1a1.Backend) []reconcile.Request { + return r.enqueueClass(ctx, be) + }), + backendPredicates...)); err != nil { + return err + } + } + // Watch Node CRUDs to update Gateway Address exposed by Service of type NodePort. // Node creation/deletion and ExternalIP updates would require update in the Gateway nPredicates := []predicate.TypedPredicate[*corev1.Node]{ diff --git a/internal/provider/kubernetes/helpers.go b/internal/provider/kubernetes/helpers.go index d3a1d972a42..a59b7604fb5 100644 --- a/internal/provider/kubernetes/helpers.go +++ b/internal/provider/kubernetes/helpers.go @@ -165,11 +165,11 @@ func validateBackendRef(ref *gwapiv1.BackendRef) error { switch { case ref == nil: return nil - case gatewayapi.GroupDerefOr(ref.Group, corev1.GroupName) != corev1.GroupName && gatewayapi.GroupDerefOr(ref.Group, corev1.GroupName) != mcsapi.GroupName: - return fmt.Errorf("invalid group; must be nil, empty string or %q", mcsapi.GroupName) - case gatewayapi.KindDerefOr(ref.Kind, gatewayapi.KindService) != gatewayapi.KindService && gatewayapi.KindDerefOr(ref.Kind, gatewayapi.KindService) != gatewayapi.KindServiceImport: - return fmt.Errorf("invalid kind %q; must be %q or %q", - *ref.BackendObjectReference.Kind, gatewayapi.KindService, gatewayapi.KindServiceImport) + case gatewayapi.GroupDerefOr(ref.Group, corev1.GroupName) != corev1.GroupName && gatewayapi.GroupDerefOr(ref.Group, corev1.GroupName) != mcsapi.GroupName && gatewayapi.GroupDerefOr(ref.Group, corev1.GroupName) != egv1a1.GroupName: + return fmt.Errorf("invalid group; must be nil, empty string %q or %q", mcsapi.GroupName, egv1a1.GroupName) + case gatewayapi.KindDerefOr(ref.Kind, gatewayapi.KindService) != gatewayapi.KindService && gatewayapi.KindDerefOr(ref.Kind, gatewayapi.KindService) != gatewayapi.KindServiceImport && gatewayapi.KindDerefOr(ref.Kind, gatewayapi.KindService) != egv1a1.KindBackend: + return fmt.Errorf("invalid kind %q; must be %q, %q or %q", + *ref.BackendObjectReference.Kind, gatewayapi.KindService, gatewayapi.KindServiceImport, egv1a1.KindBackend) } return nil diff --git a/internal/provider/kubernetes/indexers.go b/internal/provider/kubernetes/indexers.go index 80426ed1747..b99929196f4 100644 --- a/internal/provider/kubernetes/indexers.go +++ b/internal/provider/kubernetes/indexers.go @@ -60,7 +60,7 @@ func addReferenceGrantIndexers(ctx context.Context, mgr manager.Manager) error { } // addHTTPRouteIndexers adds indexing on HTTPRoute. -// - For Service, ServiceImports objects that are referenced in HTTPRoute objects via `.spec.rules.backendRefs`. +// - For Service, ServiceImports and Backend objects that are referenced in HTTPRoute objects via `.spec.rules.backendRefs`. // This helps in querying for HTTPRoutes that are affected by a particular Service CRUD. func addHTTPRouteIndexers(ctx context.Context, mgr manager.Manager) error { if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.HTTPRoute{}, gatewayHTTPRouteIndex, gatewayHTTPRouteIndexFunc); err != nil { @@ -97,7 +97,7 @@ func backendHTTPRouteIndexFunc(rawObj client.Object) []string { var backendRefs []string for _, rule := range httproute.Spec.Rules { for _, backend := range rule.BackendRefs { - if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { + if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService || string(*backend.Kind) == v1alpha1.KindBackend { // If an explicit Backend namespace is not provided, use the HTTPRoute namespace to // lookup the provided Gateway Name. backendRefs = append(backendRefs, @@ -264,7 +264,7 @@ func backendGRPCRouteIndexFunc(rawObj client.Object) []string { var backendRefs []string for _, rule := range grpcroute.Spec.Rules { for _, backend := range rule.BackendRefs { - if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { + if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService || string(*backend.Kind) == v1alpha1.KindBackend { // If an explicit Backend namespace is not provided, use the GRPCRoute namespace to // lookup the provided Gateway Name. backendRefs = append(backendRefs, @@ -314,7 +314,7 @@ func backendTLSRouteIndexFunc(rawObj client.Object) []string { var backendRefs []string for _, rule := range tlsroute.Spec.Rules { for _, backend := range rule.BackendRefs { - if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { + if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService || string(*backend.Kind) == v1alpha1.KindBackend { // If an explicit Backend namespace is not provided, use the TLSRoute namespace to // lookup the provided Gateway Name. backendRefs = append(backendRefs, @@ -364,7 +364,7 @@ func backendTCPRouteIndexFunc(rawObj client.Object) []string { var backendRefs []string for _, rule := range tcpRoute.Spec.Rules { for _, backend := range rule.BackendRefs { - if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { + if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService || string(*backend.Kind) == v1alpha1.KindBackend { // If an explicit Backend namespace is not provided, use the TCPRoute namespace to // lookup the provided Gateway Name. backendRefs = append(backendRefs, @@ -416,7 +416,7 @@ func backendUDPRouteIndexFunc(rawObj client.Object) []string { var backendRefs []string for _, rule := range udproute.Spec.Rules { for _, backend := range rule.BackendRefs { - if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { + if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService || string(*backend.Kind) == v1alpha1.KindBackend { // If an explicit Backend namespace is not provided, use the UDPRoute namespace to // lookup the provided Gateway Name. backendRefs = append(backendRefs, diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index 97714bd3a40..eb4c35eff74 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -288,6 +288,28 @@ func (r *gatewayAPIReconciler) validateServiceForReconcile(obj client.Object) bo return r.isEnvoyExtensionPolicyReferencingBackend(&nsName) } +// validateBackendForReconcile tries finding the owning Gateway of the Backend +// if it exists, finds the Gateway's Deployment, and further updates the Gateway +// status Ready condition. All Services are pushed for reconciliation. +func (r *gatewayAPIReconciler) validateBackendForReconcile(obj client.Object) bool { + be, ok := obj.(*egv1a1.Backend) + if !ok { + r.log.Info("unexpected object type, bypassing reconciliation", "object", obj) + return false + } + + nsName := utils.NamespacedName(be) + if r.isRouteReferencingBackend(&nsName) { + return true + } + + if r.isSecurityPolicyReferencingBackend(&nsName) { + return true + } + + return r.isEnvoyExtensionPolicyReferencingBackend(&nsName) +} + func (r *gatewayAPIReconciler) isSecurityPolicyReferencingBackend(nsName *types.NamespacedName) bool { spList := &egv1a1.SecurityPolicyList{} if err := r.client.List(context.Background(), spList, &client.ListOptions{ diff --git a/internal/provider/kubernetes/status_updater.go b/internal/provider/kubernetes/status_updater.go index 1b22a993187..c6bc5d7f11c 100644 --- a/internal/provider/kubernetes/status_updater.go +++ b/internal/provider/kubernetes/status_updater.go @@ -285,7 +285,14 @@ func isStatusEqual(objA, objB interface{}) bool { return true } } + case *egv1a1.Backend: + if b, ok := objB.(*egv1a1.Backend); ok { + if cmp.Equal(a.Status, b.Status, opts) { + return true + } + } } + return false } @@ -339,6 +346,8 @@ func kindOf(obj interface{}) string { kind = gatewayapi.KindBackendTLSPolicy case *unstructured.Unstructured: kind = o.GetKind() + case *egv1a1.Backend: + kind = egv1a1.KindBackend default: kind = "Unknown" } diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go index a918c159b43..e646f410944 100644 --- a/internal/xds/translator/cluster.go +++ b/internal/xds/translator/cluster.go @@ -398,17 +398,7 @@ func buildXdsClusterLoadAssignment(clusterName string, destSettings []*ir.Destin Metadata: metadata, HostIdentifier: &endpointv3.LbEndpoint_Endpoint{ Endpoint: &endpointv3.Endpoint{ - Address: &corev3.Address{ - Address: &corev3.Address_SocketAddress{ - SocketAddress: &corev3.SocketAddress{ - Protocol: corev3.SocketAddress_TCP, - Address: irEp.Host, - PortSpecifier: &corev3.SocketAddress_PortValue{ - PortValue: irEp.Port, - }, - }, - }, - }, + Address: buildAddress(irEp), }, }, } @@ -629,6 +619,29 @@ func buildXdsClusterUpstreamOptions(tcpkeepalive *ir.TCPKeepalive) *clusterv3.Up return ka } +func buildAddress(irEp *ir.DestinationEndpoint) *corev3.Address { + if irEp.Path != nil { + return &corev3.Address{ + Address: &corev3.Address_Pipe{ + Pipe: &corev3.Pipe{ + Path: *irEp.Path, + }, + }, + } + } + return &corev3.Address{ + Address: &corev3.Address_SocketAddress{ + SocketAddress: &corev3.SocketAddress{ + Protocol: corev3.SocketAddress_TCP, + Address: irEp.Host, + PortSpecifier: &corev3.SocketAddress_PortValue{ + PortValue: irEp.Port, + }, + }, + }, + } +} + func buildBackandConnectionBufferLimitBytes(bc *ir.BackendConnection) *wrappers.UInt32Value { if bc != nil && bc.BufferLimitBytes != nil { return wrapperspb.UInt32(*bc.BufferLimitBytes) diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-uds-ip.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-uds-ip.yaml new file mode 100644 index 00000000000..711913d4dfd --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-uds-ip.yaml @@ -0,0 +1,29 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.1.1.1" + port: 50001 + weight: 20 + - endpoints: + - host: "2.2.2.2" + port: 50002 + weight: 40 + - endpoints: + - path: "/etc/sock1" + weight: 20 + - endpoints: + - path: "/etc/sock2" + weight: 20 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-uds-ip.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-uds-ip.clusters.yaml new file mode 100644 index 00000000000..d53a7a1b2ce --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-uds-ip.clusters.yaml @@ -0,0 +1,17 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-uds-ip.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-uds-ip.endpoints.yaml new file mode 100644 index 00000000000..59679c57afe --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-uds-ip.endpoints.yaml @@ -0,0 +1,40 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.1.1.1 + portValue: 50001 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + region: first-route-dest/backend/0 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 2.2.2.2 + portValue: 50002 + loadBalancingWeight: 1 + loadBalancingWeight: 40 + locality: + region: first-route-dest/backend/1 + - lbEndpoints: + - endpoint: + address: + pipe: + path: /etc/sock1 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + region: first-route-dest/backend/2 + - lbEndpoints: + - endpoint: + address: + pipe: + path: /etc/sock2 + loadBalancingWeight: 1 + loadBalancingWeight: 20 + locality: + region: first-route-dest/backend/3 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-uds-ip.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-uds-ip.listeners.yaml new file mode 100644 index 00000000000..67922c7444f --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-uds-ip.listeners.yaml @@ -0,0 +1,35 @@ +- address: + socketAddress: + address: 0.0.0.0 + 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 + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + useRemoteAddress: true + name: first-listener + drainType: MODIFY_ONLY + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-uds-ip.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-uds-ip.routes.yaml new file mode 100644 index 00000000000..0b5b4bee7bb --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-uds-ip.routes.yaml @@ -0,0 +1,14 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/site/content/en/contributions/design/backend.md b/site/content/en/contributions/design/backend.md index 32596bffd32..2e3c3a899bc 100644 --- a/site/content/en/contributions/design/backend.md +++ b/site/content/en/contributions/design/backend.md @@ -33,7 +33,7 @@ The `Backend` resource is an implementation-specific Gateway-API [BackendObjectR ### Example Here is an example highlighting how a user can configure a route that forwards traffic to both a K8s Service and a Backend -that has both unix domain socket and ipv4 endpoints. A [BackendTLSPolicy][] is attached to the backend resource, enabling TLS. +that has both unix domain socket and ip endpoints. A [BackendTLSPolicy][] is attached to the backend resource, enabling TLS. ```yaml apiVersion: v1 @@ -58,7 +58,7 @@ spec: endpoints: - unix: path: /var/run/backend.sock - - ipv4: + - ip: address: 10.244.0.28 port: 3000 --- diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index f3683ceee9c..bb2d9f49e54 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -281,7 +281,7 @@ _Appears in:_ -BackendEndpoint describes a backend endpoint, which can be either a fully-qualified domain name, IPv4 address or unix domain socket +BackendEndpoint describes a backend endpoint, which can be either a fully-qualified domain name, IP address or unix domain socket corresponding to Envoy's Address: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-address _Appears in:_ @@ -291,7 +291,7 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | | `fqdn` | _[FQDNEndpoint](#fqdnendpoint)_ | false | FQDN defines a FQDN endpoint | -| `ipv4` | _[IPv4Endpoint](#ipv4endpoint)_ | false | IPv4 defines an IPv4 endpoint | +| `ip` | _[IPEndpoint](#ipendpoint)_ | false | IP defines an IP endpoint. Currently, only IPv4 Addresses are supported. | | `unix` | _[UnixSocket](#unixsocket)_ | false | Unix defines the unix domain socket endpoint | @@ -1533,10 +1533,10 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | | `fqdn` | _[FQDNEndpoint](#fqdnendpoint)_ | false | FQDN defines a FQDN endpoint | -| `ipv4` | _[IPv4Endpoint](#ipv4endpoint)_ | false | IPv4 defines an IPv4 endpoint | +| `ip` | _[IPEndpoint](#ipendpoint)_ | false | IP defines an IP endpoint. Currently, only IPv4 Addresses are supported. | | `unix` | _[UnixSocket](#unixsocket)_ | false | Unix defines the unix domain socket endpoint | -| `host` | _string_ | false | Host define the extension service hostname.
Deprecated: use the appropriate transport attribute instead (FQDN,IPv4,Unix) | -| `port` | _integer_ | false | Port defines the port the extension service is exposed on.
Deprecated: use the appropriate transport attribute instead (FQDN,IPv4,Unix) | +| `host` | _string_ | false | Host define the extension service hostname.
Deprecated: use the appropriate transport attribute instead (FQDN,IP,Unix) | +| `port` | _integer_ | false | Port defines the port the extension service is exposed on.
Deprecated: use the appropriate transport attribute instead (FQDN,IP,Unix) | | `tls` | _[ExtensionTLS](#extensiontls)_ | false | TLS defines TLS configuration for communication between Envoy Gateway and
the extension service. | @@ -1939,11 +1939,11 @@ _Appears in:_ | `passive` | _[PassiveHealthCheck](#passivehealthcheck)_ | false | Passive passive check configuration | -#### IPv4Endpoint +#### IPEndpoint -IPv4Endpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address +IPEndpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-socketaddress _Appears in:_ @@ -1952,7 +1952,7 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | -| `address` | _string_ | true | Address defines the IPv4 address of the backend endpoint. | +| `address` | _string_ | true | Address defines the IP address of the backend endpoint. | | `port` | _integer_ | true | Port defines the port of the backend endpoint. | diff --git a/site/content/zh/latest/api/extension_types.md b/site/content/zh/latest/api/extension_types.md index f3683ceee9c..bb2d9f49e54 100644 --- a/site/content/zh/latest/api/extension_types.md +++ b/site/content/zh/latest/api/extension_types.md @@ -281,7 +281,7 @@ _Appears in:_ -BackendEndpoint describes a backend endpoint, which can be either a fully-qualified domain name, IPv4 address or unix domain socket +BackendEndpoint describes a backend endpoint, which can be either a fully-qualified domain name, IP address or unix domain socket corresponding to Envoy's Address: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-address _Appears in:_ @@ -291,7 +291,7 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | | `fqdn` | _[FQDNEndpoint](#fqdnendpoint)_ | false | FQDN defines a FQDN endpoint | -| `ipv4` | _[IPv4Endpoint](#ipv4endpoint)_ | false | IPv4 defines an IPv4 endpoint | +| `ip` | _[IPEndpoint](#ipendpoint)_ | false | IP defines an IP endpoint. Currently, only IPv4 Addresses are supported. | | `unix` | _[UnixSocket](#unixsocket)_ | false | Unix defines the unix domain socket endpoint | @@ -1533,10 +1533,10 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | | `fqdn` | _[FQDNEndpoint](#fqdnendpoint)_ | false | FQDN defines a FQDN endpoint | -| `ipv4` | _[IPv4Endpoint](#ipv4endpoint)_ | false | IPv4 defines an IPv4 endpoint | +| `ip` | _[IPEndpoint](#ipendpoint)_ | false | IP defines an IP endpoint. Currently, only IPv4 Addresses are supported. | | `unix` | _[UnixSocket](#unixsocket)_ | false | Unix defines the unix domain socket endpoint | -| `host` | _string_ | false | Host define the extension service hostname.
Deprecated: use the appropriate transport attribute instead (FQDN,IPv4,Unix) | -| `port` | _integer_ | false | Port defines the port the extension service is exposed on.
Deprecated: use the appropriate transport attribute instead (FQDN,IPv4,Unix) | +| `host` | _string_ | false | Host define the extension service hostname.
Deprecated: use the appropriate transport attribute instead (FQDN,IP,Unix) | +| `port` | _integer_ | false | Port defines the port the extension service is exposed on.
Deprecated: use the appropriate transport attribute instead (FQDN,IP,Unix) | | `tls` | _[ExtensionTLS](#extensiontls)_ | false | TLS defines TLS configuration for communication between Envoy Gateway and
the extension service. | @@ -1939,11 +1939,11 @@ _Appears in:_ | `passive` | _[PassiveHealthCheck](#passivehealthcheck)_ | false | Passive passive check configuration | -#### IPv4Endpoint +#### IPEndpoint -IPv4Endpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address +IPEndpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-socketaddress _Appears in:_ @@ -1952,7 +1952,7 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | -| `address` | _string_ | true | Address defines the IPv4 address of the backend endpoint. | +| `address` | _string_ | true | Address defines the IP address of the backend endpoint. | | `port` | _integer_ | true | Port defines the port of the backend endpoint. | diff --git a/test/cel-validation/backend_test.go b/test/cel-validation/backend_test.go index ab8efd7e629..c78e22ae24c 100644 --- a/test/cel-validation/backend_test.go +++ b/test/cel-validation/backend_test.go @@ -48,7 +48,7 @@ func TestBackend(t *testing.T) { }, }, { - IPv4: &egv1a1.IPv4Endpoint{ + IP: &egv1a1.IPEndpoint{ Address: "1.1.1.1", Port: 443, }, @@ -106,7 +106,7 @@ func TestBackend(t *testing.T) { Endpoints: []egv1a1.BackendEndpoint{{}}, } }, - wantErrors: []string{"spec.endpoints[0]: Invalid value: \"object\": one of fqdn, ipv4 or unix must be specified"}, + wantErrors: []string{"spec.endpoints[0]: Invalid value: \"object\": one of fqdn, ip or unix must be specified"}, }, { desc: "Multiple addresses", @@ -126,7 +126,7 @@ func TestBackend(t *testing.T) { }, } }, - wantErrors: []string{"spec.endpoints[0]: Invalid value: \"object\": only one of fqdn, ipv4 or unix can be specified"}, + wantErrors: []string{"spec.endpoints[0]: Invalid value: \"object\": only one of fqdn, ip or unix can be specified"}, }, { desc: "Mixed types", @@ -141,7 +141,7 @@ func TestBackend(t *testing.T) { }, }, { - IPv4: &egv1a1.IPv4Endpoint{ + IP: &egv1a1.IPEndpoint{ Address: "1.1.1.1", Port: 443, }, @@ -185,38 +185,38 @@ func TestBackend(t *testing.T) { } }, wantErrors: []string{ - "spec.endpoints[0].fqdn.hostname: Invalid value: \"host name\": spec.endpoints[0].fqdn.hostname in body should match '^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'", - "spec.endpoints[1].fqdn.hostname: Invalid value: \"host_name\": spec.endpoints[1].fqdn.hostname in body should match '^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'", - "spec.endpoints[2].fqdn.hostname: Invalid value: \"hostname:443\": spec.endpoints[2].fqdn.hostname in body should match '^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'", - "spec.endpoints[3].fqdn.hostname: Invalid value: \"host.*.name\": spec.endpoints[3].fqdn.hostname in body should match '^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'", + "spec.endpoints[0].fqdn.hostname: Invalid value: \"host name\": spec.endpoints[0].fqdn.hostname in body should match '^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9]))*$'", + "spec.endpoints[1].fqdn.hostname: Invalid value: \"host_name\": spec.endpoints[1].fqdn.hostname in body should match '^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9]))*$'", + "spec.endpoints[2].fqdn.hostname: Invalid value: \"hostname:443\": spec.endpoints[2].fqdn.hostname in body should match '^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9]))*$", + "spec.endpoints[3].fqdn.hostname: Invalid value: \"host.*.name\": spec.endpoints[3].fqdn.hostname in body should match '^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9]))*$", }, }, { - desc: "Invalid IPv4", + desc: "Invalid IP", mutate: func(backend *egv1a1.Backend) { backend.Spec = egv1a1.BackendSpec{ AppProtocols: []egv1a1.AppProtocolType{egv1a1.AppProtocolTypeH2C}, Endpoints: []egv1a1.BackendEndpoint{ { - IPv4: &egv1a1.IPv4Endpoint{ + IP: &egv1a1.IPEndpoint{ Address: "300.0.0.0", Port: 443, }, }, { - IPv4: &egv1a1.IPv4Endpoint{ + IP: &egv1a1.IPEndpoint{ Address: "0.0.0.0:443", Port: 443, }, }, { - IPv4: &egv1a1.IPv4Endpoint{ + IP: &egv1a1.IPEndpoint{ Address: "0.0.0.0/12", Port: 443, }, }, { - IPv4: &egv1a1.IPv4Endpoint{ + IP: &egv1a1.IPEndpoint{ Address: "a.b.c.e", Port: 443, }, @@ -225,10 +225,10 @@ func TestBackend(t *testing.T) { } }, wantErrors: []string{ - "spec.endpoints[0].ipv4.address: Invalid value: \"300.0.0.0\": spec.endpoints[0].ipv4.address in body should match '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'", - "spec.endpoints[1].ipv4.address: Invalid value: \"0.0.0.0:443\": spec.endpoints[1].ipv4.address in body should match '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'", - "spec.endpoints[2].ipv4.address: Invalid value: \"0.0.0.0/12\": spec.endpoints[2].ipv4.address in body should match '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'", - "spec.endpoints[3].ipv4.address: Invalid value: \"a.b.c.e\": spec.endpoints[3].ipv4.address in body should match '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'", + "spec.endpoints[0].ip.address: Invalid value: \"300.0.0.0\": spec.endpoints[0].ip.address in body should match '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'", + "spec.endpoints[1].ip.address: Invalid value: \"0.0.0.0:443\": spec.endpoints[1].ip.address in body should match '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'", + "spec.endpoints[2].ip.address: Invalid value: \"0.0.0.0/12\": spec.endpoints[2].ip.address in body should match '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'", + "spec.endpoints[3].ip.address: Invalid value: \"a.b.c.e\": spec.endpoints[3].ip.address in body should match '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'", }, }, } diff --git a/test/cel-validation/envoyextensionpolicy_test.go b/test/cel-validation/envoyextensionpolicy_test.go index 773ce8640c2..29dab823004 100644 --- a/test/cel-validation/envoyextensionpolicy_test.go +++ b/test/cel-validation/envoyextensionpolicy_test.go @@ -208,7 +208,7 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { }, } }, - wantErrors: []string{" spec.extProc[0].backendRefs: Invalid value: \"array\": BackendRefs only supports Core group."}, + wantErrors: []string{"spec.extProc[0].backendRefs: Invalid value: \"array\": BackendRefs only supports Core and gateway.envoyproxy.io group"}, }, { desc: "ExtProc with invalid BackendRef Kind", @@ -236,7 +236,7 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { }, } }, - wantErrors: []string{"spec.extProc[0].backendRefs: Invalid value: \"array\": BackendRefs only supports Service kind."}, + wantErrors: []string{"spec.extProc[0].backendRefs: Invalid value: \"array\": BackendRefs only supports Service and Backend kind"}, }, { desc: "ExtProc with invalid fields", diff --git a/test/config/gatewayclass.yaml b/test/config/gatewayclass.yaml index 4067b66d58d..e4a801b6b8e 100644 --- a/test/config/gatewayclass.yaml +++ b/test/config/gatewayclass.yaml @@ -16,6 +16,20 @@ metadata: name: proxy-config namespace: envoy-gateway-system spec: + provider: + type: Kubernetes + kubernetes: + envoyDeployment: + container: + volumeMounts: + - mountPath: /var/run/ext-proc + name: socket-dir + pod: + volumes: + - name: socket-dir + hostPath: + path: /var/run/ext-proc + type: '' telemetry: metrics: prometheus: {} diff --git a/test/e2e/base/manifests.yaml b/test/e2e/base/manifests.yaml index 5217c46594b..c1e08e63c8b 100644 --- a/test/e2e/base/manifests.yaml +++ b/test/e2e/base/manifests.yaml @@ -753,6 +753,108 @@ spec: from: Same --- apiVersion: v1 +data: + ca.crt: | + -----BEGIN CERTIFICATE----- + MIIDQzCCAiugAwIBAgIBATANBgkqhkiG9w0BAQsFADBCMRMwEQYDVQQKEwpFbnZv + eVByb3h5MRAwDgYDVQQLEwdHYXRld2F5MRkwFwYDVQQDExBFbnZveSBHYXRld2F5 + IENBMCAXDTI0MDMxMDE1MzIxN1oYDzIxMjQwMzEwMTYzMjE3WjBCMRMwEQYDVQQK + EwpFbnZveVByb3h5MRAwDgYDVQQLEwdHYXRld2F5MRkwFwYDVQQDExBFbnZveSBH + YXRld2F5IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7ZFmGB4e + m1KdGEohAZBfqydAEGLDHJ1YyfHWdd+vBAevdW64bZx3pggJOtgCnePuFd02rDQS + dlsJlX/6mFtoQilo6wvxDSJRfaTDbtfTjw+7k8yfd/Jsmh0RWG+UeyI7Na9sXAz7 + b57mpxsCoNowzeK5ETiOGGNWPcjENJkSnBarz5muN00xIZWBU+yN5PLJNxZvxpZJ + Ol/SSI8sno0e0PxAmp3fe7QaXiZj/TAGJPGuTJkUxrHqyZGJtYUxsS8A0dT1zBjj + izA5Dp+b5yzYo23Hh7BgpbZ7X4gsDThFuwCD6fHyepuv2zHPqvSsdqg2hAhDp91R + zrn7a9GxG2VSIwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw + AwEB/zAdBgNVHQ4EFgQUUpP1aZ1M2KIuPPWrNPDV2c5CngowDQYJKoZIhvcNAQEL + BQADggEBAGSEkAVz+Z0qS4FmA0q4SCpIIq64bsdEjiUzev7pK1LEK0/Y28QBPixV + cUXfax18VPR9pls1JgXto9qY+C0hnRZic6611QTJlWK1p6dinQ/eDdYCBC+nv5xx + ssASwmplIxMvj3S1qF6dr7sMI2ZVD5HElTWdO19UBLyhiKKZW2KxDsYj+5NRwGFe + G+JuDgq7njUM8mdyYk0NehefdBUEUUCQtnwUtW95/429XwqQROuRDteGT9kjD+Y5 + ea5mW4mfqLeuGJXZs9bdWjKKdLQPrn9IshPysWqz2Hz8dQ1f7N9/g8UWVSjd4cyx + S5EAolzVv0yB7wHCWCgfG/ckdOTUNnE= + -----END CERTIFICATE----- +kind: ConfigMap +metadata: + name: backend-tls-checks-certificate + namespace: gateway-conformance-infra +--- +apiVersion: v1 +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURZVENDQWttZ0F3SUJBZ0lSQUpiK2x5QTJqZCtlUmRMTzR4Sm5kWVF3RFFZSktvWklodmNOQVFFTEJRQXcKUWpFVE1CRUdBMVVFQ2hNS1JXNTJiM2xRY205NGVURVFNQTRHQTFVRUN4TUhSMkYwWlhkaGVURVpNQmNHQTFVRQpBeE1RUlc1MmIza2dSMkYwWlhkaGVTQkRRVEFnRncweU5EQXpNVEF4TlRNeU1UZGFHQTh5TVRJME1ETXhNREUyCk16SXhOMW93SkRFUU1BNEdBMVVFQ2hNSFFXTnRaU0JEYnpFUU1BNEdBMVVFQXhNSFpHVm1ZWFZzZERDQ0FTSXcKRFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUtGUnI2cVV1WFN1N3J5bHcvVmZXbm1kM0RXWgpTcGxDUFR6QUh1V3NpOVVrbW5rTVhNOXN3Y1VQZFUyd2NNSHd1bDNpNGJwTlRkUGVWRG04K3JUVXNmaHMySWZuCmhHNW9WV0JnTkJXVEYzRnpiUmgvc3orK3p6MlBnZ0Fpb3NjYmEyVm5qaExyOUM3a0Q3QnRYNVlvSENGQ3lhT24Kem9WNVdNSnBBNHNCeGdOdkpXSU5aRUNnOUlmSWxSMDZMTGlNTXJCRTVRS2cvTG5EUkpuTEZEVFZCTDdzallpVQpZdVZtRWczMXJaOVpsNXViZ09xSU9uU2ROM2RNM1hhUnBCTWFGVXg5UDlQcmhjS3l5NVRkQ3g2MHBIYXMvaFIxCmFjcEp5VmdmRFVDdXNUUFphVFo1eXM0cmhib1l3WDN5cnZKN29lMHM4QmRZU2thT1NBTElDaU9PWGtVQ0F3RUEKQWFOdU1Hd3dEZ1lEVlIwUEFRSC9CQVFEQWdXZ01CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRkJ3TUJNQXdHQTFVZApFd0VCL3dRQ01BQXdId1lEVlIwakJCZ3dGb0FVVXBQMWFaMU0yS0l1UFBXck5QRFYyYzVDbmdvd0ZnWURWUjBSCkJBOHdEWUlMWlhoaGJYQnNaUzVqYjIwd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFBMkk1MmhrcEwwTXZmejQKeDk3ZjV6dlR5a1VtRWhDSVowN0g0anM0WVg2a1hLWVBzRDBlaGJFbzZUSWgyMkpWMkpyWnRuaWhMQnRGQStuUQp2Zk9QcE1LRnJMUU1DWVozMk9Na045T1pWbmNyMmpQNzNhaE9SaWloaGVBczJYTUtybHZmVWVKTFJrSlBlSVB6CnR2TlVacWExMmZ4T0Jsdy9hV1NqVk9lRDVMVm5nUStrQksydGRoL08xSjFWRGgzdVU3RHNZUThmRm1UcWR6ZzYKUWhtbjhaTXFIS3lNeitOdkt1d1h5eEtyeFZKVEl1QzJXZHhGWlZZMzdtZzJ5Vm9OdFhpSFNQMXpxVWV4SHNEKwpzUDBsZy9jUDdlaitOY3Q5WnpudUZBc2U4cUNDZnlaL2hPQ2NCblZabG1GUFgzRCtJSEpVWUpGaWVkYndsZHljCmw1eG1jaFU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBb1ZHdnFwUzVkSzd1dktYRDlWOWFlWjNjTlpsS21VSTlQTUFlNWF5TDFTU2FlUXhjCnoyekJ4UTkxVGJCd3dmQzZYZUxodWsxTjA5NVVPYno2dE5TeCtHelloK2VFYm1oVllHQTBGWk1YY1hOdEdIK3oKUDc3UFBZK0NBQ0tpeHh0clpXZU9FdXYwTHVRUHNHMWZsaWdjSVVMSm82Zk9oWGxZd21rRGl3SEdBMjhsWWcxawpRS0QwaDhpVkhUb3N1SXd5c0VUbEFxRDh1Y05FbWNzVU5OVUV2dXlOaUpSaTVXWVNEZld0bjFtWG01dUE2b2c2CmRKMDNkMHpkZHBHa0V4b1ZUSDAvMCt1RndyTExsTjBMSHJTa2RxeitGSFZweWtuSldCOE5RSzZ4TTlscE5ubksKeml1RnVoakJmZkt1OG51aDdTendGMWhLUm81SUFzZ0tJNDVlUlFJREFRQUJBb0lCQVFDVGlZUGh2TGVJa2R6aQpSN0RhbnVTK1NiUDJpVVlDdU9RTXhhRDhhVHhTS1hIbHQzckNjak1kcVMrZFovc1lSTFFOM2N5WWVNN3ZNRzFUCmlSUzVnYlZyQVJGZjZrdmlOaVd2U1EwWmxqZGdtVEp6cjRjZWk4STZDUi9hUTlNZnltSUVraHNNRHlSNkpqWjcKSXV6REJkZ0VTM0xpN0R3ak1vSU0rOEl6eGVGMWpTT1ErTjlLcTB3QzMzVzFuOVdIYXZWcWZvcjI0bmVySG9FcwozNmlUMncvdkU1dFJBTFlEbjh6MFp5YUM1d3Nnb3FyTG5UWXlMcnVKWnNGa1NxN25GWEE3cjhXL0dLQjBoL3ZaCmNzYkRlWU1WMjJNckdRTzhYSlAwM3J0cm9DQWJmUUhRd3lEbnpsTFJ3blNGRmhjV0F5UW9qbkozb0RQbzhZaXoKam1meVd5WlpBb0dCQU0vZGtqMGhFZm05SHBBL1dyTGVEb0V5WWtKL3N1R3RyWlpSNS9INnJieHphQ2FlQ3B0UApZQ25JcnBoMjRVYWFvaXFJY0pnazRXRjBmU3RhRnh0SkxSYXpBVElUUFlCZjF0OEEwYkhjN3UxMExiWlZkMG5uCk1lWVJPYlhzQXlvdmxNcm1ZclBPWWFXSEtJL1oyT3NLeC83UkhTcnEwZm1ZcUFYSXpzK2V1Ryt6QW9HQkFNYXMKem9YdlJwVDZGNndYaU5QemFqamc5MHJFMFhZZ0g3VkEvWHJsbUp5MVFRYy8rZzJ1ZXVYMGJ5aVhYY0FMY3BINAoybFlYcEZaelNPRkd6Z01DMEtuQkJyWmxsYWIweUczbWhsWjRtbkFhbmtSUFh4bWpDdmgvZmtkYStlQ1RCMFdHCjBOY3RQSFVvSk9GNWpLNmtxVy9rWVpkWVRPV1FjczNybURFWCtENG5Bb0dCQUwwdkhRenp6MGRyMzZoTGNRSUEKWmxVaUJSb2UzVERYQUhraWZLYllqMDFJQUErOW9VdXZWNGRQOWRBZnluS1hCR2NQbk9Kc0ZwQzdFN3prRnNtbgp0UmpHdkp6VnRCRGxxVXQzbEdKOEFSMHVzdmdUR3ltdytOSTY5VHBrM3BDRGs3bURLMndZdHZpUFpkUmU0alV4CnI4cDBpa1pvUjhrU0xrSnRmQVNzb1pKUEFvR0FWSTk4bjNrR082WnVxT3FqYkVMd2RTRWJZQkdCYlp1aW8wejAKRm5qZWllU0R0d2c5NzlEUnNrcGxmWXRmZGJ2cG1jT25lbms1a3lvaVhPLzhBMEFSZkE4U1FsUGViRjlIWjY5MApnaDEyN2p3R0hPRURneS9vSFhoMlVQeWgyam42SUZlUFQrYUxFdnB4S0I3S0NCTkJvc1E3M1dUUjVldWpVWTN6CkN3SSt3SVVDZ1lFQXJVQ0k4cng3MVd4S3A0dnNObTJpM2JlT3lYa3dVaFhKUmhmL0cwZk5vc2FhT0RvVEdNT1oKVlRRci9hVWJlQ2pWMlZENTEyVkJEQlZnYUNnZ1ZZS3pSMXpJSDFlMXZzVjhQVjN1Snh0Q2FLT3daTHV4OS9HQQp0QzJOKzFTY05GWkxtU3Z0MzU2WG5EL3VwRUcyeVMydmFURDU1K3FVUlVFWk1TWDlPdFpSL2JBPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= +kind: Secret +metadata: + name: backend-tls-checks-certificate + namespace: gateway-conformance-infra +type: kubernetes.io/tls +--- +apiVersion: v1 +kind: Service +metadata: + name: tls-backend-2 + namespace: gateway-conformance-infra +spec: + selector: + app: tls-backend-2 + ports: + - protocol: TCP + port: 443 + targetPort: 8443 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tls-backend-2 + namespace: gateway-conformance-infra + labels: + app: tls-backend-2 +spec: + replicas: 1 + selector: + matchLabels: + app: tls-backend-2 + template: + metadata: + labels: + app: tls-backend-2 + spec: + containers: + - name: tls-backend + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e + volumeMounts: + - name: secret-volume + mountPath: /etc/secret-volume + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SERVICE_NAME + value: tls-backend-2 + - name: TLS_SERVER_CERT + value: /etc/secret-volume/crt + - name: TLS_SERVER_PRIVKEY + value: /etc/secret-volume/key + resources: + requests: + cpu: 10m + volumes: + - name: secret-volume + secret: + secretName: backend-tls-checks-certificate + items: + - key: tls.crt + path: crt + - key: tls.key + path: key +--- +apiVersion: v1 data: tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURZVENDQWttZ0F3SUJBZ0lSQUpiK2x5QTJqZCtlUmRMTzR4Sm5kWVF3RFFZSktvWklodmNOQVFFTEJRQXcKUWpFVE1CRUdBMVVFQ2hNS1JXNTJiM2xRY205NGVURVFNQTRHQTFVRUN4TUhSMkYwWlhkaGVURVpNQmNHQTFVRQpBeE1RUlc1MmIza2dSMkYwWlhkaGVTQkRRVEFnRncweU5EQXpNVEF4TlRNeU1UZGFHQTh5TVRJME1ETXhNREUyCk16SXhOMW93SkRFUU1BNEdBMVVFQ2hNSFFXTnRaU0JEYnpFUU1BNEdBMVVFQXhNSFpHVm1ZWFZzZERDQ0FTSXcKRFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUtGUnI2cVV1WFN1N3J5bHcvVmZXbm1kM0RXWgpTcGxDUFR6QUh1V3NpOVVrbW5rTVhNOXN3Y1VQZFUyd2NNSHd1bDNpNGJwTlRkUGVWRG04K3JUVXNmaHMySWZuCmhHNW9WV0JnTkJXVEYzRnpiUmgvc3orK3p6MlBnZ0Fpb3NjYmEyVm5qaExyOUM3a0Q3QnRYNVlvSENGQ3lhT24Kem9WNVdNSnBBNHNCeGdOdkpXSU5aRUNnOUlmSWxSMDZMTGlNTXJCRTVRS2cvTG5EUkpuTEZEVFZCTDdzallpVQpZdVZtRWczMXJaOVpsNXViZ09xSU9uU2ROM2RNM1hhUnBCTWFGVXg5UDlQcmhjS3l5NVRkQ3g2MHBIYXMvaFIxCmFjcEp5VmdmRFVDdXNUUFphVFo1eXM0cmhib1l3WDN5cnZKN29lMHM4QmRZU2thT1NBTElDaU9PWGtVQ0F3RUEKQWFOdU1Hd3dEZ1lEVlIwUEFRSC9CQVFEQWdXZ01CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRkJ3TUJNQXdHQTFVZApFd0VCL3dRQ01BQXdId1lEVlIwakJCZ3dGb0FVVXBQMWFaMU0yS0l1UFBXck5QRFYyYzVDbmdvd0ZnWURWUjBSCkJBOHdEWUlMWlhoaGJYQnNaUzVqYjIwd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFBMkk1MmhrcEwwTXZmejQKeDk3ZjV6dlR5a1VtRWhDSVowN0g0anM0WVg2a1hLWVBzRDBlaGJFbzZUSWgyMkpWMkpyWnRuaWhMQnRGQStuUQp2Zk9QcE1LRnJMUU1DWVozMk9Na045T1pWbmNyMmpQNzNhaE9SaWloaGVBczJYTUtybHZmVWVKTFJrSlBlSVB6CnR2TlVacWExMmZ4T0Jsdy9hV1NqVk9lRDVMVm5nUStrQksydGRoL08xSjFWRGgzdVU3RHNZUThmRm1UcWR6ZzYKUWhtbjhaTXFIS3lNeitOdkt1d1h5eEtyeFZKVEl1QzJXZHhGWlZZMzdtZzJ5Vm9OdFhpSFNQMXpxVWV4SHNEKwpzUDBsZy9jUDdlaitOY3Q5WnpudUZBc2U4cUNDZnlaL2hPQ2NCblZabG1GUFgzRCtJSEpVWUpGaWVkYndsZHljCmw1eG1jaFU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBb1ZHdnFwUzVkSzd1dktYRDlWOWFlWjNjTlpsS21VSTlQTUFlNWF5TDFTU2FlUXhjCnoyekJ4UTkxVGJCd3dmQzZYZUxodWsxTjA5NVVPYno2dE5TeCtHelloK2VFYm1oVllHQTBGWk1YY1hOdEdIK3oKUDc3UFBZK0NBQ0tpeHh0clpXZU9FdXYwTHVRUHNHMWZsaWdjSVVMSm82Zk9oWGxZd21rRGl3SEdBMjhsWWcxawpRS0QwaDhpVkhUb3N1SXd5c0VUbEFxRDh1Y05FbWNzVU5OVUV2dXlOaUpSaTVXWVNEZld0bjFtWG01dUE2b2c2CmRKMDNkMHpkZHBHa0V4b1ZUSDAvMCt1RndyTExsTjBMSHJTa2RxeitGSFZweWtuSldCOE5RSzZ4TTlscE5ubksKeml1RnVoakJmZkt1OG51aDdTendGMWhLUm81SUFzZ0tJNDVlUlFJREFRQUJBb0lCQVFDVGlZUGh2TGVJa2R6aQpSN0RhbnVTK1NiUDJpVVlDdU9RTXhhRDhhVHhTS1hIbHQzckNjak1kcVMrZFovc1lSTFFOM2N5WWVNN3ZNRzFUCmlSUzVnYlZyQVJGZjZrdmlOaVd2U1EwWmxqZGdtVEp6cjRjZWk4STZDUi9hUTlNZnltSUVraHNNRHlSNkpqWjcKSXV6REJkZ0VTM0xpN0R3ak1vSU0rOEl6eGVGMWpTT1ErTjlLcTB3QzMzVzFuOVdIYXZWcWZvcjI0bmVySG9FcwozNmlUMncvdkU1dFJBTFlEbjh6MFp5YUM1d3Nnb3FyTG5UWXlMcnVKWnNGa1NxN25GWEE3cjhXL0dLQjBoL3ZaCmNzYkRlWU1WMjJNckdRTzhYSlAwM3J0cm9DQWJmUUhRd3lEbnpsTFJ3blNGRmhjV0F5UW9qbkozb0RQbzhZaXoKam1meVd5WlpBb0dCQU0vZGtqMGhFZm05SHBBL1dyTGVEb0V5WWtKL3N1R3RyWlpSNS9INnJieHphQ2FlQ3B0UApZQ25JcnBoMjRVYWFvaXFJY0pnazRXRjBmU3RhRnh0SkxSYXpBVElUUFlCZjF0OEEwYkhjN3UxMExiWlZkMG5uCk1lWVJPYlhzQXlvdmxNcm1ZclBPWWFXSEtJL1oyT3NLeC83UkhTcnEwZm1ZcUFYSXpzK2V1Ryt6QW9HQkFNYXMKem9YdlJwVDZGNndYaU5QemFqamc5MHJFMFhZZ0g3VkEvWHJsbUp5MVFRYy8rZzJ1ZXVYMGJ5aVhYY0FMY3BINAoybFlYcEZaelNPRkd6Z01DMEtuQkJyWmxsYWIweUczbWhsWjRtbkFhbmtSUFh4bWpDdmgvZmtkYStlQ1RCMFdHCjBOY3RQSFVvSk9GNWpLNmtxVy9rWVpkWVRPV1FjczNybURFWCtENG5Bb0dCQUwwdkhRenp6MGRyMzZoTGNRSUEKWmxVaUJSb2UzVERYQUhraWZLYllqMDFJQUErOW9VdXZWNGRQOWRBZnluS1hCR2NQbk9Kc0ZwQzdFN3prRnNtbgp0UmpHdkp6VnRCRGxxVXQzbEdKOEFSMHVzdmdUR3ltdytOSTY5VHBrM3BDRGs3bURLMndZdHZpUFpkUmU0alV4CnI4cDBpa1pvUjhrU0xrSnRmQVNzb1pKUEFvR0FWSTk4bjNrR082WnVxT3FqYkVMd2RTRWJZQkdCYlp1aW8wejAKRm5qZWllU0R0d2c5NzlEUnNrcGxmWXRmZGJ2cG1jT25lbms1a3lvaVhPLzhBMEFSZkE4U1FsUGViRjlIWjY5MApnaDEyN2p3R0hPRURneS9vSFhoMlVQeWgyam42SUZlUFQrYUxFdnB4S0I3S0NCTkJvc1E3M1dUUjVldWpVWTN6CkN3SSt3SVVDZ1lFQXJVQ0k4cng3MVd4S3A0dnNObTJpM2JlT3lYa3dVaFhKUmhmL0cwZk5vc2FhT0RvVEdNT1oKVlRRci9hVWJlQ2pWMlZENTEyVkJEQlZnYUNnZ1ZZS3pSMXpJSDFlMXZzVjhQVjN1Snh0Q2FLT3daTHV4OS9HQQp0QzJOKzFTY05GWkxtU3Z0MzU2WG5EL3VwRUcyeVMydmFURDU1K3FVUlVFWk1TWDlPdFpSL2JBPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= diff --git a/test/e2e/testdata/backend-tls.yaml b/test/e2e/testdata/backend-tls.yaml index cdd6960c6d2..f00218ab99c 100644 --- a/test/e2e/testdata/backend-tls.yaml +++ b/test/e2e/testdata/backend-tls.yaml @@ -1,105 +1,3 @@ -apiVersion: v1 -data: - ca.crt: | - -----BEGIN CERTIFICATE----- - MIIDQzCCAiugAwIBAgIBATANBgkqhkiG9w0BAQsFADBCMRMwEQYDVQQKEwpFbnZv - eVByb3h5MRAwDgYDVQQLEwdHYXRld2F5MRkwFwYDVQQDExBFbnZveSBHYXRld2F5 - IENBMCAXDTI0MDMxMDE1MzIxN1oYDzIxMjQwMzEwMTYzMjE3WjBCMRMwEQYDVQQK - EwpFbnZveVByb3h5MRAwDgYDVQQLEwdHYXRld2F5MRkwFwYDVQQDExBFbnZveSBH - YXRld2F5IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7ZFmGB4e - m1KdGEohAZBfqydAEGLDHJ1YyfHWdd+vBAevdW64bZx3pggJOtgCnePuFd02rDQS - dlsJlX/6mFtoQilo6wvxDSJRfaTDbtfTjw+7k8yfd/Jsmh0RWG+UeyI7Na9sXAz7 - b57mpxsCoNowzeK5ETiOGGNWPcjENJkSnBarz5muN00xIZWBU+yN5PLJNxZvxpZJ - Ol/SSI8sno0e0PxAmp3fe7QaXiZj/TAGJPGuTJkUxrHqyZGJtYUxsS8A0dT1zBjj - izA5Dp+b5yzYo23Hh7BgpbZ7X4gsDThFuwCD6fHyepuv2zHPqvSsdqg2hAhDp91R - zrn7a9GxG2VSIwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw - AwEB/zAdBgNVHQ4EFgQUUpP1aZ1M2KIuPPWrNPDV2c5CngowDQYJKoZIhvcNAQEL - BQADggEBAGSEkAVz+Z0qS4FmA0q4SCpIIq64bsdEjiUzev7pK1LEK0/Y28QBPixV - cUXfax18VPR9pls1JgXto9qY+C0hnRZic6611QTJlWK1p6dinQ/eDdYCBC+nv5xx - ssASwmplIxMvj3S1qF6dr7sMI2ZVD5HElTWdO19UBLyhiKKZW2KxDsYj+5NRwGFe - G+JuDgq7njUM8mdyYk0NehefdBUEUUCQtnwUtW95/429XwqQROuRDteGT9kjD+Y5 - ea5mW4mfqLeuGJXZs9bdWjKKdLQPrn9IshPysWqz2Hz8dQ1f7N9/g8UWVSjd4cyx - S5EAolzVv0yB7wHCWCgfG/ckdOTUNnE= - -----END CERTIFICATE----- -kind: ConfigMap -metadata: - name: backend-tls-checks-certificate - namespace: gateway-conformance-infra ---- -apiVersion: v1 -data: - tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURZVENDQWttZ0F3SUJBZ0lSQUpiK2x5QTJqZCtlUmRMTzR4Sm5kWVF3RFFZSktvWklodmNOQVFFTEJRQXcKUWpFVE1CRUdBMVVFQ2hNS1JXNTJiM2xRY205NGVURVFNQTRHQTFVRUN4TUhSMkYwWlhkaGVURVpNQmNHQTFVRQpBeE1RUlc1MmIza2dSMkYwWlhkaGVTQkRRVEFnRncweU5EQXpNVEF4TlRNeU1UZGFHQTh5TVRJME1ETXhNREUyCk16SXhOMW93SkRFUU1BNEdBMVVFQ2hNSFFXTnRaU0JEYnpFUU1BNEdBMVVFQXhNSFpHVm1ZWFZzZERDQ0FTSXcKRFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUtGUnI2cVV1WFN1N3J5bHcvVmZXbm1kM0RXWgpTcGxDUFR6QUh1V3NpOVVrbW5rTVhNOXN3Y1VQZFUyd2NNSHd1bDNpNGJwTlRkUGVWRG04K3JUVXNmaHMySWZuCmhHNW9WV0JnTkJXVEYzRnpiUmgvc3orK3p6MlBnZ0Fpb3NjYmEyVm5qaExyOUM3a0Q3QnRYNVlvSENGQ3lhT24Kem9WNVdNSnBBNHNCeGdOdkpXSU5aRUNnOUlmSWxSMDZMTGlNTXJCRTVRS2cvTG5EUkpuTEZEVFZCTDdzallpVQpZdVZtRWczMXJaOVpsNXViZ09xSU9uU2ROM2RNM1hhUnBCTWFGVXg5UDlQcmhjS3l5NVRkQ3g2MHBIYXMvaFIxCmFjcEp5VmdmRFVDdXNUUFphVFo1eXM0cmhib1l3WDN5cnZKN29lMHM4QmRZU2thT1NBTElDaU9PWGtVQ0F3RUEKQWFOdU1Hd3dEZ1lEVlIwUEFRSC9CQVFEQWdXZ01CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRkJ3TUJNQXdHQTFVZApFd0VCL3dRQ01BQXdId1lEVlIwakJCZ3dGb0FVVXBQMWFaMU0yS0l1UFBXck5QRFYyYzVDbmdvd0ZnWURWUjBSCkJBOHdEWUlMWlhoaGJYQnNaUzVqYjIwd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFBMkk1MmhrcEwwTXZmejQKeDk3ZjV6dlR5a1VtRWhDSVowN0g0anM0WVg2a1hLWVBzRDBlaGJFbzZUSWgyMkpWMkpyWnRuaWhMQnRGQStuUQp2Zk9QcE1LRnJMUU1DWVozMk9Na045T1pWbmNyMmpQNzNhaE9SaWloaGVBczJYTUtybHZmVWVKTFJrSlBlSVB6CnR2TlVacWExMmZ4T0Jsdy9hV1NqVk9lRDVMVm5nUStrQksydGRoL08xSjFWRGgzdVU3RHNZUThmRm1UcWR6ZzYKUWhtbjhaTXFIS3lNeitOdkt1d1h5eEtyeFZKVEl1QzJXZHhGWlZZMzdtZzJ5Vm9OdFhpSFNQMXpxVWV4SHNEKwpzUDBsZy9jUDdlaitOY3Q5WnpudUZBc2U4cUNDZnlaL2hPQ2NCblZabG1GUFgzRCtJSEpVWUpGaWVkYndsZHljCmw1eG1jaFU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K - tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBb1ZHdnFwUzVkSzd1dktYRDlWOWFlWjNjTlpsS21VSTlQTUFlNWF5TDFTU2FlUXhjCnoyekJ4UTkxVGJCd3dmQzZYZUxodWsxTjA5NVVPYno2dE5TeCtHelloK2VFYm1oVllHQTBGWk1YY1hOdEdIK3oKUDc3UFBZK0NBQ0tpeHh0clpXZU9FdXYwTHVRUHNHMWZsaWdjSVVMSm82Zk9oWGxZd21rRGl3SEdBMjhsWWcxawpRS0QwaDhpVkhUb3N1SXd5c0VUbEFxRDh1Y05FbWNzVU5OVUV2dXlOaUpSaTVXWVNEZld0bjFtWG01dUE2b2c2CmRKMDNkMHpkZHBHa0V4b1ZUSDAvMCt1RndyTExsTjBMSHJTa2RxeitGSFZweWtuSldCOE5RSzZ4TTlscE5ubksKeml1RnVoakJmZkt1OG51aDdTendGMWhLUm81SUFzZ0tJNDVlUlFJREFRQUJBb0lCQVFDVGlZUGh2TGVJa2R6aQpSN0RhbnVTK1NiUDJpVVlDdU9RTXhhRDhhVHhTS1hIbHQzckNjak1kcVMrZFovc1lSTFFOM2N5WWVNN3ZNRzFUCmlSUzVnYlZyQVJGZjZrdmlOaVd2U1EwWmxqZGdtVEp6cjRjZWk4STZDUi9hUTlNZnltSUVraHNNRHlSNkpqWjcKSXV6REJkZ0VTM0xpN0R3ak1vSU0rOEl6eGVGMWpTT1ErTjlLcTB3QzMzVzFuOVdIYXZWcWZvcjI0bmVySG9FcwozNmlUMncvdkU1dFJBTFlEbjh6MFp5YUM1d3Nnb3FyTG5UWXlMcnVKWnNGa1NxN25GWEE3cjhXL0dLQjBoL3ZaCmNzYkRlWU1WMjJNckdRTzhYSlAwM3J0cm9DQWJmUUhRd3lEbnpsTFJ3blNGRmhjV0F5UW9qbkozb0RQbzhZaXoKam1meVd5WlpBb0dCQU0vZGtqMGhFZm05SHBBL1dyTGVEb0V5WWtKL3N1R3RyWlpSNS9INnJieHphQ2FlQ3B0UApZQ25JcnBoMjRVYWFvaXFJY0pnazRXRjBmU3RhRnh0SkxSYXpBVElUUFlCZjF0OEEwYkhjN3UxMExiWlZkMG5uCk1lWVJPYlhzQXlvdmxNcm1ZclBPWWFXSEtJL1oyT3NLeC83UkhTcnEwZm1ZcUFYSXpzK2V1Ryt6QW9HQkFNYXMKem9YdlJwVDZGNndYaU5QemFqamc5MHJFMFhZZ0g3VkEvWHJsbUp5MVFRYy8rZzJ1ZXVYMGJ5aVhYY0FMY3BINAoybFlYcEZaelNPRkd6Z01DMEtuQkJyWmxsYWIweUczbWhsWjRtbkFhbmtSUFh4bWpDdmgvZmtkYStlQ1RCMFdHCjBOY3RQSFVvSk9GNWpLNmtxVy9rWVpkWVRPV1FjczNybURFWCtENG5Bb0dCQUwwdkhRenp6MGRyMzZoTGNRSUEKWmxVaUJSb2UzVERYQUhraWZLYllqMDFJQUErOW9VdXZWNGRQOWRBZnluS1hCR2NQbk9Kc0ZwQzdFN3prRnNtbgp0UmpHdkp6VnRCRGxxVXQzbEdKOEFSMHVzdmdUR3ltdytOSTY5VHBrM3BDRGs3bURLMndZdHZpUFpkUmU0alV4CnI4cDBpa1pvUjhrU0xrSnRmQVNzb1pKUEFvR0FWSTk4bjNrR082WnVxT3FqYkVMd2RTRWJZQkdCYlp1aW8wejAKRm5qZWllU0R0d2c5NzlEUnNrcGxmWXRmZGJ2cG1jT25lbms1a3lvaVhPLzhBMEFSZkE4U1FsUGViRjlIWjY5MApnaDEyN2p3R0hPRURneS9vSFhoMlVQeWgyam42SUZlUFQrYUxFdnB4S0I3S0NCTkJvc1E3M1dUUjVldWpVWTN6CkN3SSt3SVVDZ1lFQXJVQ0k4cng3MVd4S3A0dnNObTJpM2JlT3lYa3dVaFhKUmhmL0cwZk5vc2FhT0RvVEdNT1oKVlRRci9hVWJlQ2pWMlZENTEyVkJEQlZnYUNnZ1ZZS3pSMXpJSDFlMXZzVjhQVjN1Snh0Q2FLT3daTHV4OS9HQQp0QzJOKzFTY05GWkxtU3Z0MzU2WG5EL3VwRUcyeVMydmFURDU1K3FVUlVFWk1TWDlPdFpSL2JBPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= -kind: Secret -metadata: - name: backend-tls-checks-certificate - namespace: gateway-conformance-infra -type: kubernetes.io/tls ---- -apiVersion: v1 -kind: Service -metadata: - name: tls-backend-2 - namespace: gateway-conformance-infra -spec: - selector: - app: tls-backend-2 - ports: - - protocol: TCP - port: 443 - targetPort: 8443 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: tls-backend-2 - namespace: gateway-conformance-infra - labels: - app: tls-backend-2 -spec: - replicas: 1 - selector: - matchLabels: - app: tls-backend-2 - template: - metadata: - labels: - app: tls-backend-2 - spec: - containers: - - name: tls-backend - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e - volumeMounts: - - name: secret-volume - mountPath: /etc/secret-volume - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: SERVICE_NAME - value: tls-backend-2 - - name: TLS_SERVER_CERT - value: /etc/secret-volume/crt - - name: TLS_SERVER_PRIVKEY - value: /etc/secret-volume/key - resources: - requests: - cpu: 10m - volumes: - - name: secret-volume - secret: - secretName: backend-tls-checks-certificate - items: - - key: tls.crt - path: crt - - key: tls.key - path: key ---- apiVersion: gateway.networking.k8s.io/v1alpha3 kind: BackendTLSPolicy metadata: diff --git a/test/e2e/testdata/ext-proc-envoyextensionpolicy.yaml b/test/e2e/testdata/ext-proc-envoyextensionpolicy.yaml index b4031a94d87..b495a7b9f7e 100644 --- a/test/e2e/testdata/ext-proc-envoyextensionpolicy.yaml +++ b/test/e2e/testdata/ext-proc-envoyextensionpolicy.yaml @@ -87,3 +87,68 @@ spec: group: '' kind: ConfigMap hostname: grpc-ext-proc.envoygateway +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-with-extproc-uds-tls + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + hostnames: ["www.example.com"] + rules: + - matches: + - path: + type: PathPrefix + value: /uds-processor + backendRefs: + - name: infra-backend-v1 + port: 8080 +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: Backend +metadata: + name: grpc-uds-ext-proc + namespace: gateway-conformance-infra +spec: + endpoints: + - unix: + path: /var/run/ext-proc/extproc.sock +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyExtensionPolicy +metadata: + name: ext-proc-uds-test + namespace: gateway-conformance-infra +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: http-with-extproc-uds-tls + extProc: + - backendRefs: + - kind: Backend + group: gateway.envoyproxy.io + name: grpc-uds-ext-proc + namespace: gateway-conformance-infra + processingMode: + request: {} + response: {} +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: policy-btls-uds-extproc + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: grpc-uds-ext-proc + validation: + caCertificateRefs: + - name: grpc-ext-proc-ca + group: '' + kind: ConfigMap + hostname: grpc-ext-proc.envoygateway diff --git a/test/e2e/testdata/ext-proc-service.yaml b/test/e2e/testdata/ext-proc-service.yaml index e9c48e7fc2f..23b325f2031 100644 --- a/test/e2e/testdata/ext-proc-service.yaml +++ b/test/e2e/testdata/ext-proc-service.yaml @@ -99,7 +99,6 @@ data: log.Fatalf("Failed to load TLS credentials: %v", err) } gs := grpc.NewServer(grpc.Creds(creds)) - envoy_service_proc_v3.RegisterExternalProcessorServer(gs, &extProcServer{}) go func() { @@ -109,6 +108,40 @@ data: } }() + // Create Unix listener + gus := grpc.NewServer(grpc.Creds(creds)) + envoy_service_proc_v3.RegisterExternalProcessorServer(gus, &extProcServer{}) + + udsAddr := "/var/run/ext-proc/extproc.sock" + if _, err := os.Stat(udsAddr); err == nil { + if err := os.RemoveAll(udsAddr); err != nil { + log.Fatalf("failed to remove: %v", err) + } + } + + ul, err := net.Listen("unix", udsAddr) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + + err = os.Chmod(udsAddr, 0700) + if err != nil { + log.Fatalf("failed to set permissions: %v", err) + } + + // envoy distroless uid + err = os.Chown(udsAddr, 65532, 0) + if err != nil { + log.Fatalf("failed to set permissions: %v", err) + } + + go func() { + err = gus.Serve(ul) + if err != nil { + log.Fatalf("failed to serve: %v", err) + } + }() + http.HandleFunc("/healthz", healthCheckHandler) err = http.ListenAndServe(":8080", nil) if err != nil { @@ -364,7 +397,7 @@ spec: command: - sh - "-c" - - "cp -a /app /app-live && cd /app-live && go run . --certPath=/app-live/certs/ " + - "cd /app && go run . --certPath=/app/certs/" image: golang:1.22.3-alpine ports: - containerPort: 8000 @@ -373,6 +406,8 @@ spec: mountPath: /app - name: grpc-ext-proc-secret mountPath: /app/certs + - name: socket-dir + mountPath: /var/run/ext-proc/ readinessProbe: httpGet: path: /healthz @@ -389,6 +424,10 @@ spec: path: server.crt - key: tls.key path: server.key + - name: socket-dir + hostPath: + path: /var/run/ext-proc/ + type: DirectoryOrCreate --- apiVersion: v1 kind: Service diff --git a/test/e2e/testdata/httproute-to-backend-fqdn-http2.yaml b/test/e2e/testdata/httproute-to-backend-fqdn-http2.yaml new file mode 100644 index 00000000000..15131291fbc --- /dev/null +++ b/test/e2e/testdata/httproute-to-backend-fqdn-http2.yaml @@ -0,0 +1,30 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: httproute-to-backend-fqdn-http2 + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /backend-fqdn-http2 + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn-http2 +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: Backend +metadata: + name: backend-fqdn-http2 + namespace: gateway-conformance-infra +spec: + appProtocols: + - gateway.envoyproxy.io/h2c + endpoints: + - fqdn: + hostname: infra-backend-v1.gateway-conformance-infra.svc.cluster.local + port: 8081 diff --git a/test/e2e/testdata/httproute-to-backend-fqdn-tls.yaml b/test/e2e/testdata/httproute-to-backend-fqdn-tls.yaml new file mode 100644 index 00000000000..b3f2f34f375 --- /dev/null +++ b/test/e2e/testdata/httproute-to-backend-fqdn-tls.yaml @@ -0,0 +1,45 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: httproute-to-fqdn-backend-tls + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /backend-fqdn-tls + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn-tls +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: Backend +metadata: + name: backend-fqdn-tls + namespace: gateway-conformance-infra +spec: + endpoints: + - fqdn: + hostname: tls-backend-2.gateway-conformance-infra.svc.cluster.local + port: 443 +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: backend-fqdn-tls-btls + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn-tls + validation: + caCertificateRefs: + - name: backend-tls-checks-certificate + group: "" + kind: ConfigMap + hostname: example.com diff --git a/test/e2e/testdata/httproute-to-backend-fqdn.yaml b/test/e2e/testdata/httproute-to-backend-fqdn.yaml new file mode 100644 index 00000000000..bef40eecdf3 --- /dev/null +++ b/test/e2e/testdata/httproute-to-backend-fqdn.yaml @@ -0,0 +1,28 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: httproute-to-backend-fqdn + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /backend-fqdn + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn-http2 +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: Backend +metadata: + name: backend-fqdn + namespace: gateway-conformance-infra +spec: + endpoints: + - fqdn: + hostname: infra-backend-v1.gateway-conformance-infra.svc.cluster.local + port: 8080 diff --git a/test/e2e/testdata/httproute-to-backend-ip.yaml b/test/e2e/testdata/httproute-to-backend-ip.yaml new file mode 100644 index 00000000000..de1116d3f8e --- /dev/null +++ b/test/e2e/testdata/httproute-to-backend-ip.yaml @@ -0,0 +1,47 @@ +apiVersion: v1 +kind: Service +metadata: + name: infra-backend-v1-clusterip + namespace: gateway-conformance-infra +spec: + selector: + app: infra-backend-v1 + clusterIP: 10.96.96.96 + ports: + - protocol: TCP + port: 8080 + name: http11 + targetPort: 3000 + - protocol: TCP + port: 8081 + name: http2 + targetPort: 3001 +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: httproute-to-backend-ip + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /backend-ip + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: Backend +metadata: + name: backend-ip + namespace: gateway-conformance-infra +spec: + endpoints: + - ip: + address: 10.96.96.96 + port: 8080 diff --git a/test/e2e/tests/ext_proc.go b/test/e2e/tests/ext_proc.go index eb069380b7b..afa10772551 100644 --- a/test/e2e/tests/ext_proc.go +++ b/test/e2e/tests/ext_proc.go @@ -133,5 +133,58 @@ var ExtProcTest = suite.ConformanceTest{ t.Errorf("failed to compare request and response: %v", err) } }) + + t.Run("http route with uds ext proc", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "http-with-ext-proc", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + ancestorRef := gwv1a2.ParentReference{ + Group: gatewayapi.GroupPtr(gwv1.GroupName), + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Namespace: gatewayapi.NamespacePtr(gwNN.Namespace), + Name: gwv1.ObjectName(gwNN.Name), + } + EnvoyExtensionPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "ext-proc-uds-test", Namespace: ns}, suite.ControllerName, ancestorRef) + + podReady := corev1.PodCondition{Type: corev1.PodReady, Status: corev1.ConditionTrue} + + // Wait for the grpc ext auth service pod to be ready + WaitForPods(t, suite.Client, ns, map[string]string{"app": "grpc-ext-proc"}, corev1.PodRunning, podReady) + + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Host: "www.example.com", + Path: "/uds-processor", + Headers: map[string]string{ + "x-request-ext-processed": "true", // header added by ext-processor to backend-bound request + "x-request-client-header-received": "original", // this is the original client header preserved by ext-proc in a new header + "x-request-client-header": "mutated", // this is the mutated value expected to reach upstream + }, + }, + Response: http.Response{ + StatusCode: 200, + Headers: map[string]string{ + "x-response-ext-processed": "true", // header added by ext-processor to client-bound response + }, + }, + Namespace: ns, + } + + req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + + // add a request header that will be mutated by ext-proc + req.Headers["x-request-client-header"] = []string{"original"} + + cReq, cResp, err := suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Errorf("failed to get expected response: %v", err) + } + + if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil { + t.Errorf("failed to compare request and response: %v", err) + } + }) }, } diff --git a/test/e2e/tests/route_with_backend.go b/test/e2e/tests/route_with_backend.go new file mode 100644 index 00000000000..fadb195c3d9 --- /dev/null +++ b/test/e2e/tests/route_with_backend.go @@ -0,0 +1,110 @@ +// 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 +// +build e2e + +package tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, EnvoyGatewayBackendTest) +} + +var EnvoyGatewayBackendTest = suite.ConformanceTest{ + ShortName: "EnvoyGatewayBackendTest", + Description: "Routes with a backend ref to a backend", + Manifests: []string{ + "testdata/httproute-to-backend-fqdn.yaml", + "testdata/httproute-to-backend-ip.yaml", + "testdata/httproute-to-backend-fqdn-http2.yaml", + "testdata/httproute-to-backend-fqdn-tls.yaml", + }, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + t.Run("of type FQDN", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "httproute-to-backend-fqdn", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Path: "/backend-fqdn", + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse) + }) + + t.Run("of type IP", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "httproute-to-backend-ip", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Path: "/backend-ip", + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse) + }) + + t.Run("of type FQDN with HTTP2", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "httproute-to-backend-fqdn-http2", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Path: "/backend-fqdn-http2", + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse) + }) + + t.Run("of type FQDN with a backend TLS Policy", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "httproute-to-fqdn-backend-tls", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Path: "/backend-fqdn-tls", + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse) + }) + }, +} diff --git a/test/helm/default-config.out.yaml b/test/helm/default-config.out.yaml index 25326c67742..5184640ee6d 100644 --- a/test/helm/default-config.out.yaml +++ b/test/helm/default-config.out.yaml @@ -126,6 +126,7 @@ rules: - backendtrafficpolicies - securitypolicies - envoyextensionpolicies + - backends verbs: - get - list @@ -138,6 +139,7 @@ rules: - backendtrafficpolicies/status - securitypolicies/status - envoyextensionpolicies/status + - backends/status verbs: - update - apiGroups: diff --git a/test/helm/deployment-images-config.out.yaml b/test/helm/deployment-images-config.out.yaml index b13dc2261a5..f0c15a289e5 100644 --- a/test/helm/deployment-images-config.out.yaml +++ b/test/helm/deployment-images-config.out.yaml @@ -126,6 +126,7 @@ rules: - backendtrafficpolicies - securitypolicies - envoyextensionpolicies + - backends verbs: - get - list @@ -138,6 +139,7 @@ rules: - backendtrafficpolicies/status - securitypolicies/status - envoyextensionpolicies/status + - backends/status verbs: - update - apiGroups: diff --git a/test/helm/envoy-gateway-config.out.yaml b/test/helm/envoy-gateway-config.out.yaml index 612306e1f0e..dd9742e52f6 100644 --- a/test/helm/envoy-gateway-config.out.yaml +++ b/test/helm/envoy-gateway-config.out.yaml @@ -128,6 +128,7 @@ rules: - backendtrafficpolicies - securitypolicies - envoyextensionpolicies + - backends verbs: - get - list @@ -140,6 +141,7 @@ rules: - backendtrafficpolicies/status - securitypolicies/status - envoyextensionpolicies/status + - backends/status verbs: - update - apiGroups: diff --git a/test/helm/global-images-config.out.yaml b/test/helm/global-images-config.out.yaml index 89788eaef1a..51d4df43502 100644 --- a/test/helm/global-images-config.out.yaml +++ b/test/helm/global-images-config.out.yaml @@ -130,6 +130,7 @@ rules: - backendtrafficpolicies - securitypolicies - envoyextensionpolicies + - backends verbs: - get - list @@ -142,6 +143,7 @@ rules: - backendtrafficpolicies/status - securitypolicies/status - envoyextensionpolicies/status + - backends/status verbs: - update - apiGroups: