diff --git a/artifacts/flagger/crd.yaml b/artifacts/flagger/crd.yaml index 69ecf0759..be9209e48 100644 --- a/artifacts/flagger/crd.yaml +++ b/artifacts/flagger/crd.yaml @@ -897,36 +897,6 @@ spec: type: string backendRef: &backendRef type: object - x-kubernetes-validations: - - message: Must have port for Service reference - rule: - "(size(self.group) == 0 && self.kind == 'Service') - ? has(self.port) : true" - description: |- - HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. - - Note that when a namespace different than the local namespace is specified, a - ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - - - When the BackendRef points to a Kubernetes Service, implementations SHOULD - honor the appProtocol field if it is set for the target Service Port. - - Implementations supporting appProtocol SHOULD recognize the Kubernetes - Standard Application Protocols defined in KEP-3726. - - If a Service appProtocol isn't specified, an implementation MAY infer the - backend protocol through its own means. Implementations MAY infer the - protocol from the Route type referring to the backend Service. - - If a Route is not able to send traffic to the backend using the specified - protocol then the backend is considered invalid. Implementations MUST set the - "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. - - properties: filters: description: |- @@ -936,42 +906,19 @@ spec: Support: Implementation-specific (For broader support of filters, use the Filters field in HTTPRouteRule.) items: - description: |- - HTTPRouteFilter defines processing steps that must be completed during the - request or response lifecycle. HTTPRouteFilters are meant as an extension - point to express processing that may be done in Gateway implementations. Some - examples include request or response modification, implementing - authentication strategies, rate-limiting, and traffic shaping. API - guarantee/conformance is defined based on the type of the filter. properties: extensionRef: - description: |- - ExtensionRef is an optional, implementation-specific extension to the - "filter" behavior. For example, resource "myroutefilter" in group - "networking.example.net"). ExtensionRef MUST NOT be used for core and - extended filters. - - This filter can be used multiple times within the same rule. - - Support: Implementation-specific properties: group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: - description: - Kind is kind of the referent. For - example "HTTPRoute" or "Service". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: - description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string @@ -981,54 +928,16 @@ spec: - name type: object requestHeaderModifier: - description: |- - RequestHeaderModifier defines a schema for a filter that modifies request - headers. - - Support: Core properties: add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - Input: - GET /foo HTTP/1.1 - my-header: foo - - Config: - add: - - name: "my-header" - value: "bar,baz" - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz items: - description: - HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: - description: - Value is the value of HTTP - Header to be matched. maxLength: 4096 minLength: 1 type: string @@ -1042,70 +951,20 @@ spec: - name x-kubernetes-list-type: map remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - Config: - remove: ["my-header1", "my-header3"] - - Output: - GET /foo HTTP/1.1 - my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - Input: - GET /foo HTTP/1.1 - my-header: foo - - Config: - set: - - name: "my-header" - value: "bar" - - Output: - GET /foo HTTP/1.1 - my-header: bar items: - description: - HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: - description: - Value is the value of HTTP - Header to be matched. maxLength: 4096 minLength: 1 type: string @@ -1120,100 +979,30 @@ spec: x-kubernetes-list-type: map type: object requestMirror: - description: |+ - RequestMirror defines a schema for a filter that mirrors requests. - Requests are sent to the specified destination, but responses from - that destination are ignored. - - This filter can be used multiple times within the same rule. Note that - not all implementations will be able to support mirroring to multiple - backends. - - Support: Extended - properties: backendRef: - description: |- - BackendRef references a resource where mirrored requests are sent. - - Mirrored requests must be sent only to a single destination endpoint - within this BackendRef, irrespective of how many endpoints are present - within this BackendRef. - - If the referent cannot be found, this BackendRef is invalid and must be - dropped from the Gateway. The controller must ensure the "ResolvedRefs" - condition on the Route status is set to `status: False` and not configure - this backend in the underlying implementation. - - If there is a cross-namespace reference to an *existing* object - that is not allowed by a ReferenceGrant, the controller must ensure the - "ResolvedRefs" condition on the Route is set to `status: False`, - with the "RefNotPermitted" reason and not configure this backend in the - underlying implementation. - - In either error case, the Message of the `ResolvedRefs` Condition - should be used to provide more detail about the problem. - - Support: Extended for Kubernetes Service - - Support: Implementation-specific for any other resource properties: group: default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service - description: |- - Kind is the Kubernetes resource kind of the referent. For example - "Service". - - Defaults to "Service" when not specified. - - ExternalName services can refer to CNAME DNS records that may live - outside of the cluster and as such are difficult to reason about in - terms of conformance. They also may not be safe to forward to (see - CVE-2021-25740 for more information). Implementations SHOULD NOT - support ExternalName Services. - - Support: Core (Services with a type other than ExternalName) - - Support: Implementation-specific (Services with type ExternalName) maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: - description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: - description: |- - Namespace is the namespace of the backend. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: - description: |- - Port specifies the destination port number to use for this resource. - Port is required when the referent is a Kubernetes Service. In this - case, the port number is the service port number, not the target port. - For other resources, destination port might be derived from the referent - resource or this field. format: int32 maximum: 65535 minimum: 1 @@ -1230,68 +1019,21 @@ spec: - backendRef type: object requestRedirect: - description: |- - RequestRedirect defines a schema for a filter that responds to the - request with an HTTP redirection. - - Support: Core properties: hostname: - description: |- - Hostname is the hostname to be used in the value of the `Location` - header in the response. - When empty, the hostname in the `Host` header of the request is used. - - Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: - description: |- - Path defines parameters used to modify the path of the incoming request. - The modified path is then used to construct the `Location` header. When - empty, the request path is used as-is. - - Support: Extended properties: replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: - description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: - description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch @@ -1325,120 +1067,33 @@ spec: "has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" port: - description: |- - Port is the port to be used in the value of the `Location` - header in the response. - - If no port is specified, the redirect port MUST be derived using the - following rules: - - * If redirect scheme is not-empty, the redirect port MUST be the well-known - port associated with the redirect scheme. Specifically "http" to port 80 - and "https" to port 443. If the redirect scheme does not have a - well-known port, the listener port of the Gateway SHOULD be used. - * If redirect scheme is empty, the redirect port MUST be the Gateway - Listener port. - - Implementations SHOULD NOT add the port number in the 'Location' - header in the following cases: - - * A Location header that will use HTTP (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 80. - * A Location header that will use HTTPS (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 443. - - Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer scheme: - description: |- - Scheme is the scheme to be used in the value of the `Location` header in - the response. When empty, the scheme of the request is used. - - Scheme redirects can affect the port of the redirect, for more information, - refer to the documentation for the port field of this filter. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - Support: Extended enum: - http - https type: string statusCode: default: 302 - description: |- - StatusCode is the HTTP status code to be used in response. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - Support: Core enum: - 301 - 302 type: integer type: object responseHeaderModifier: - description: |- - ResponseHeaderModifier defines a schema for a filter that modifies response - headers. - - Support: Extended properties: add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - Input: - GET /foo HTTP/1.1 - my-header: foo - - Config: - add: - - name: "my-header" - value: "bar,baz" - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz items: - description: - HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: - description: - Value is the value of HTTP - Header to be matched. maxLength: 4096 minLength: 1 type: string @@ -1452,70 +1107,20 @@ spec: - name x-kubernetes-list-type: map remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - Config: - remove: ["my-header1", "my-header3"] - - Output: - GET /foo HTTP/1.1 - my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - Input: - GET /foo HTTP/1.1 - my-header: foo - - Config: - set: - - name: "my-header" - value: "bar" - - Output: - GET /foo HTTP/1.1 - my-header: bar items: - description: - HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: - description: - Value is the value of HTTP - Header to be matched. maxLength: 4096 minLength: 1 type: string @@ -1530,39 +1135,6 @@ spec: x-kubernetes-list-type: map type: object type: - description: |- - Type identifies the type of filter to apply. As with other API fields, - types are classified into three conformance levels: - - - Core: Filter types and their corresponding configuration defined by - "Support: Core" in this package, e.g. "RequestHeaderModifier". All - implementations must support core filters. - - - Extended: Filter types and their corresponding configuration defined by - "Support: Extended" in this package, e.g. "RequestMirror". Implementers - are encouraged to support extended filters. - - - Implementation-specific: Filters that are defined and supported by - specific vendors. - In the future, filters showing convergence in behavior across multiple - implementations will be considered for inclusion in extended or core - conformance levels. Filter-specific configuration for such filters - is specified using the ExtensionRef field. `Type` should be set to - "ExtensionRef" for custom filters. - - Implementers are encouraged to define custom implementation types to - extend the core API with implementation-specific behavior. - - If a reference to a custom filter type cannot be resolved, the filter - MUST NOT be skipped. Instead, requests that would have been processed by - that filter MUST receive a HTTP error response. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. enum: - RequestHeaderModifier - ResponseHeaderModifier @@ -1572,64 +1144,21 @@ spec: - ExtensionRef type: string urlRewrite: - description: |- - URLRewrite defines a schema for a filter that modifies a request during forwarding. - - Support: Extended properties: hostname: - description: |- - Hostname is the value to be used to replace the Host header value during - forwarding. - - Support: Extended maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: - description: |- - Path defines a path rewrite. - - Support: Extended properties: replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: - description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: - description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch @@ -1760,67 +1289,40 @@ spec: rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 - group: - default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Service - description: |- - Kind is the Kubernetes resource kind of the referent. For example - "Service". - - Defaults to "Service" when not specified. - - ExternalName services can refer to CNAME DNS records that may live - outside of the cluster and as such are difficult to reason about in - terms of conformance. They also may not be safe to forward to (see - CVE-2021-25740 for more information). Implementations SHOULD NOT - support ExternalName Services. - - Support: Core (Services with a type other than ExternalName) - - Support: Implementation-specific (Services with type ExternalName) - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the backend. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - port: - description: |- - Port specifies the destination port number to use for this resource. - Port is required when the referent is a Kubernetes Service. In this - case, the port number is the service port number, not the target port. - For other resources, destination port might be derived from the referent - resource or this field. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - + ref: + group: + default: "" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' canary: description: Metadata to add to the canary service type: object diff --git a/charts/flagger/crds/crd.yaml b/charts/flagger/crds/crd.yaml index 69ecf0759..be9209e48 100644 --- a/charts/flagger/crds/crd.yaml +++ b/charts/flagger/crds/crd.yaml @@ -897,36 +897,6 @@ spec: type: string backendRef: &backendRef type: object - x-kubernetes-validations: - - message: Must have port for Service reference - rule: - "(size(self.group) == 0 && self.kind == 'Service') - ? has(self.port) : true" - description: |- - HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. - - Note that when a namespace different than the local namespace is specified, a - ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - - - When the BackendRef points to a Kubernetes Service, implementations SHOULD - honor the appProtocol field if it is set for the target Service Port. - - Implementations supporting appProtocol SHOULD recognize the Kubernetes - Standard Application Protocols defined in KEP-3726. - - If a Service appProtocol isn't specified, an implementation MAY infer the - backend protocol through its own means. Implementations MAY infer the - protocol from the Route type referring to the backend Service. - - If a Route is not able to send traffic to the backend using the specified - protocol then the backend is considered invalid. Implementations MUST set the - "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. - - properties: filters: description: |- @@ -936,42 +906,19 @@ spec: Support: Implementation-specific (For broader support of filters, use the Filters field in HTTPRouteRule.) items: - description: |- - HTTPRouteFilter defines processing steps that must be completed during the - request or response lifecycle. HTTPRouteFilters are meant as an extension - point to express processing that may be done in Gateway implementations. Some - examples include request or response modification, implementing - authentication strategies, rate-limiting, and traffic shaping. API - guarantee/conformance is defined based on the type of the filter. properties: extensionRef: - description: |- - ExtensionRef is an optional, implementation-specific extension to the - "filter" behavior. For example, resource "myroutefilter" in group - "networking.example.net"). ExtensionRef MUST NOT be used for core and - extended filters. - - This filter can be used multiple times within the same rule. - - Support: Implementation-specific properties: group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: - description: - Kind is kind of the referent. For - example "HTTPRoute" or "Service". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: - description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string @@ -981,54 +928,16 @@ spec: - name type: object requestHeaderModifier: - description: |- - RequestHeaderModifier defines a schema for a filter that modifies request - headers. - - Support: Core properties: add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - Input: - GET /foo HTTP/1.1 - my-header: foo - - Config: - add: - - name: "my-header" - value: "bar,baz" - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz items: - description: - HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: - description: - Value is the value of HTTP - Header to be matched. maxLength: 4096 minLength: 1 type: string @@ -1042,70 +951,20 @@ spec: - name x-kubernetes-list-type: map remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - Config: - remove: ["my-header1", "my-header3"] - - Output: - GET /foo HTTP/1.1 - my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - Input: - GET /foo HTTP/1.1 - my-header: foo - - Config: - set: - - name: "my-header" - value: "bar" - - Output: - GET /foo HTTP/1.1 - my-header: bar items: - description: - HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: - description: - Value is the value of HTTP - Header to be matched. maxLength: 4096 minLength: 1 type: string @@ -1120,100 +979,30 @@ spec: x-kubernetes-list-type: map type: object requestMirror: - description: |+ - RequestMirror defines a schema for a filter that mirrors requests. - Requests are sent to the specified destination, but responses from - that destination are ignored. - - This filter can be used multiple times within the same rule. Note that - not all implementations will be able to support mirroring to multiple - backends. - - Support: Extended - properties: backendRef: - description: |- - BackendRef references a resource where mirrored requests are sent. - - Mirrored requests must be sent only to a single destination endpoint - within this BackendRef, irrespective of how many endpoints are present - within this BackendRef. - - If the referent cannot be found, this BackendRef is invalid and must be - dropped from the Gateway. The controller must ensure the "ResolvedRefs" - condition on the Route status is set to `status: False` and not configure - this backend in the underlying implementation. - - If there is a cross-namespace reference to an *existing* object - that is not allowed by a ReferenceGrant, the controller must ensure the - "ResolvedRefs" condition on the Route is set to `status: False`, - with the "RefNotPermitted" reason and not configure this backend in the - underlying implementation. - - In either error case, the Message of the `ResolvedRefs` Condition - should be used to provide more detail about the problem. - - Support: Extended for Kubernetes Service - - Support: Implementation-specific for any other resource properties: group: default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service - description: |- - Kind is the Kubernetes resource kind of the referent. For example - "Service". - - Defaults to "Service" when not specified. - - ExternalName services can refer to CNAME DNS records that may live - outside of the cluster and as such are difficult to reason about in - terms of conformance. They also may not be safe to forward to (see - CVE-2021-25740 for more information). Implementations SHOULD NOT - support ExternalName Services. - - Support: Core (Services with a type other than ExternalName) - - Support: Implementation-specific (Services with type ExternalName) maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: - description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: - description: |- - Namespace is the namespace of the backend. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: - description: |- - Port specifies the destination port number to use for this resource. - Port is required when the referent is a Kubernetes Service. In this - case, the port number is the service port number, not the target port. - For other resources, destination port might be derived from the referent - resource or this field. format: int32 maximum: 65535 minimum: 1 @@ -1230,68 +1019,21 @@ spec: - backendRef type: object requestRedirect: - description: |- - RequestRedirect defines a schema for a filter that responds to the - request with an HTTP redirection. - - Support: Core properties: hostname: - description: |- - Hostname is the hostname to be used in the value of the `Location` - header in the response. - When empty, the hostname in the `Host` header of the request is used. - - Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: - description: |- - Path defines parameters used to modify the path of the incoming request. - The modified path is then used to construct the `Location` header. When - empty, the request path is used as-is. - - Support: Extended properties: replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: - description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: - description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch @@ -1325,120 +1067,33 @@ spec: "has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" port: - description: |- - Port is the port to be used in the value of the `Location` - header in the response. - - If no port is specified, the redirect port MUST be derived using the - following rules: - - * If redirect scheme is not-empty, the redirect port MUST be the well-known - port associated with the redirect scheme. Specifically "http" to port 80 - and "https" to port 443. If the redirect scheme does not have a - well-known port, the listener port of the Gateway SHOULD be used. - * If redirect scheme is empty, the redirect port MUST be the Gateway - Listener port. - - Implementations SHOULD NOT add the port number in the 'Location' - header in the following cases: - - * A Location header that will use HTTP (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 80. - * A Location header that will use HTTPS (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 443. - - Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer scheme: - description: |- - Scheme is the scheme to be used in the value of the `Location` header in - the response. When empty, the scheme of the request is used. - - Scheme redirects can affect the port of the redirect, for more information, - refer to the documentation for the port field of this filter. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - Support: Extended enum: - http - https type: string statusCode: default: 302 - description: |- - StatusCode is the HTTP status code to be used in response. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - Support: Core enum: - 301 - 302 type: integer type: object responseHeaderModifier: - description: |- - ResponseHeaderModifier defines a schema for a filter that modifies response - headers. - - Support: Extended properties: add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - Input: - GET /foo HTTP/1.1 - my-header: foo - - Config: - add: - - name: "my-header" - value: "bar,baz" - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz items: - description: - HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: - description: - Value is the value of HTTP - Header to be matched. maxLength: 4096 minLength: 1 type: string @@ -1452,70 +1107,20 @@ spec: - name x-kubernetes-list-type: map remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - Config: - remove: ["my-header1", "my-header3"] - - Output: - GET /foo HTTP/1.1 - my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - Input: - GET /foo HTTP/1.1 - my-header: foo - - Config: - set: - - name: "my-header" - value: "bar" - - Output: - GET /foo HTTP/1.1 - my-header: bar items: - description: - HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: - description: - Value is the value of HTTP - Header to be matched. maxLength: 4096 minLength: 1 type: string @@ -1530,39 +1135,6 @@ spec: x-kubernetes-list-type: map type: object type: - description: |- - Type identifies the type of filter to apply. As with other API fields, - types are classified into three conformance levels: - - - Core: Filter types and their corresponding configuration defined by - "Support: Core" in this package, e.g. "RequestHeaderModifier". All - implementations must support core filters. - - - Extended: Filter types and their corresponding configuration defined by - "Support: Extended" in this package, e.g. "RequestMirror". Implementers - are encouraged to support extended filters. - - - Implementation-specific: Filters that are defined and supported by - specific vendors. - In the future, filters showing convergence in behavior across multiple - implementations will be considered for inclusion in extended or core - conformance levels. Filter-specific configuration for such filters - is specified using the ExtensionRef field. `Type` should be set to - "ExtensionRef" for custom filters. - - Implementers are encouraged to define custom implementation types to - extend the core API with implementation-specific behavior. - - If a reference to a custom filter type cannot be resolved, the filter - MUST NOT be skipped. Instead, requests that would have been processed by - that filter MUST receive a HTTP error response. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. enum: - RequestHeaderModifier - ResponseHeaderModifier @@ -1572,64 +1144,21 @@ spec: - ExtensionRef type: string urlRewrite: - description: |- - URLRewrite defines a schema for a filter that modifies a request during forwarding. - - Support: Extended properties: hostname: - description: |- - Hostname is the value to be used to replace the Host header value during - forwarding. - - Support: Extended maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: - description: |- - Path defines a path rewrite. - - Support: Extended properties: replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: - description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: - description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch @@ -1760,67 +1289,40 @@ spec: rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 - group: - default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Service - description: |- - Kind is the Kubernetes resource kind of the referent. For example - "Service". - - Defaults to "Service" when not specified. - - ExternalName services can refer to CNAME DNS records that may live - outside of the cluster and as such are difficult to reason about in - terms of conformance. They also may not be safe to forward to (see - CVE-2021-25740 for more information). Implementations SHOULD NOT - support ExternalName Services. - - Support: Core (Services with a type other than ExternalName) - - Support: Implementation-specific (Services with type ExternalName) - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the backend. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - port: - description: |- - Port specifies the destination port number to use for this resource. - Port is required when the referent is a Kubernetes Service. In this - case, the port number is the service port number, not the target port. - For other resources, destination port might be derived from the referent - resource or this field. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - + ref: + group: + default: "" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' canary: description: Metadata to add to the canary service type: object diff --git a/kustomize/base/flagger/crd.yaml b/kustomize/base/flagger/crd.yaml index 69ecf0759..be9209e48 100644 --- a/kustomize/base/flagger/crd.yaml +++ b/kustomize/base/flagger/crd.yaml @@ -897,36 +897,6 @@ spec: type: string backendRef: &backendRef type: object - x-kubernetes-validations: - - message: Must have port for Service reference - rule: - "(size(self.group) == 0 && self.kind == 'Service') - ? has(self.port) : true" - description: |- - HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. - - Note that when a namespace different than the local namespace is specified, a - ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - - - When the BackendRef points to a Kubernetes Service, implementations SHOULD - honor the appProtocol field if it is set for the target Service Port. - - Implementations supporting appProtocol SHOULD recognize the Kubernetes - Standard Application Protocols defined in KEP-3726. - - If a Service appProtocol isn't specified, an implementation MAY infer the - backend protocol through its own means. Implementations MAY infer the - protocol from the Route type referring to the backend Service. - - If a Route is not able to send traffic to the backend using the specified - protocol then the backend is considered invalid. Implementations MUST set the - "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. - - properties: filters: description: |- @@ -936,42 +906,19 @@ spec: Support: Implementation-specific (For broader support of filters, use the Filters field in HTTPRouteRule.) items: - description: |- - HTTPRouteFilter defines processing steps that must be completed during the - request or response lifecycle. HTTPRouteFilters are meant as an extension - point to express processing that may be done in Gateway implementations. Some - examples include request or response modification, implementing - authentication strategies, rate-limiting, and traffic shaping. API - guarantee/conformance is defined based on the type of the filter. properties: extensionRef: - description: |- - ExtensionRef is an optional, implementation-specific extension to the - "filter" behavior. For example, resource "myroutefilter" in group - "networking.example.net"). ExtensionRef MUST NOT be used for core and - extended filters. - - This filter can be used multiple times within the same rule. - - Support: Implementation-specific properties: group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: - description: - Kind is kind of the referent. For - example "HTTPRoute" or "Service". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: - description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string @@ -981,54 +928,16 @@ spec: - name type: object requestHeaderModifier: - description: |- - RequestHeaderModifier defines a schema for a filter that modifies request - headers. - - Support: Core properties: add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - Input: - GET /foo HTTP/1.1 - my-header: foo - - Config: - add: - - name: "my-header" - value: "bar,baz" - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz items: - description: - HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: - description: - Value is the value of HTTP - Header to be matched. maxLength: 4096 minLength: 1 type: string @@ -1042,70 +951,20 @@ spec: - name x-kubernetes-list-type: map remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - Config: - remove: ["my-header1", "my-header3"] - - Output: - GET /foo HTTP/1.1 - my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - Input: - GET /foo HTTP/1.1 - my-header: foo - - Config: - set: - - name: "my-header" - value: "bar" - - Output: - GET /foo HTTP/1.1 - my-header: bar items: - description: - HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: - description: - Value is the value of HTTP - Header to be matched. maxLength: 4096 minLength: 1 type: string @@ -1120,100 +979,30 @@ spec: x-kubernetes-list-type: map type: object requestMirror: - description: |+ - RequestMirror defines a schema for a filter that mirrors requests. - Requests are sent to the specified destination, but responses from - that destination are ignored. - - This filter can be used multiple times within the same rule. Note that - not all implementations will be able to support mirroring to multiple - backends. - - Support: Extended - properties: backendRef: - description: |- - BackendRef references a resource where mirrored requests are sent. - - Mirrored requests must be sent only to a single destination endpoint - within this BackendRef, irrespective of how many endpoints are present - within this BackendRef. - - If the referent cannot be found, this BackendRef is invalid and must be - dropped from the Gateway. The controller must ensure the "ResolvedRefs" - condition on the Route status is set to `status: False` and not configure - this backend in the underlying implementation. - - If there is a cross-namespace reference to an *existing* object - that is not allowed by a ReferenceGrant, the controller must ensure the - "ResolvedRefs" condition on the Route is set to `status: False`, - with the "RefNotPermitted" reason and not configure this backend in the - underlying implementation. - - In either error case, the Message of the `ResolvedRefs` Condition - should be used to provide more detail about the problem. - - Support: Extended for Kubernetes Service - - Support: Implementation-specific for any other resource properties: group: default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service - description: |- - Kind is the Kubernetes resource kind of the referent. For example - "Service". - - Defaults to "Service" when not specified. - - ExternalName services can refer to CNAME DNS records that may live - outside of the cluster and as such are difficult to reason about in - terms of conformance. They also may not be safe to forward to (see - CVE-2021-25740 for more information). Implementations SHOULD NOT - support ExternalName Services. - - Support: Core (Services with a type other than ExternalName) - - Support: Implementation-specific (Services with type ExternalName) maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: - description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: - description: |- - Namespace is the namespace of the backend. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: - description: |- - Port specifies the destination port number to use for this resource. - Port is required when the referent is a Kubernetes Service. In this - case, the port number is the service port number, not the target port. - For other resources, destination port might be derived from the referent - resource or this field. format: int32 maximum: 65535 minimum: 1 @@ -1230,68 +1019,21 @@ spec: - backendRef type: object requestRedirect: - description: |- - RequestRedirect defines a schema for a filter that responds to the - request with an HTTP redirection. - - Support: Core properties: hostname: - description: |- - Hostname is the hostname to be used in the value of the `Location` - header in the response. - When empty, the hostname in the `Host` header of the request is used. - - Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: - description: |- - Path defines parameters used to modify the path of the incoming request. - The modified path is then used to construct the `Location` header. When - empty, the request path is used as-is. - - Support: Extended properties: replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: - description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: - description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch @@ -1325,120 +1067,33 @@ spec: "has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" port: - description: |- - Port is the port to be used in the value of the `Location` - header in the response. - - If no port is specified, the redirect port MUST be derived using the - following rules: - - * If redirect scheme is not-empty, the redirect port MUST be the well-known - port associated with the redirect scheme. Specifically "http" to port 80 - and "https" to port 443. If the redirect scheme does not have a - well-known port, the listener port of the Gateway SHOULD be used. - * If redirect scheme is empty, the redirect port MUST be the Gateway - Listener port. - - Implementations SHOULD NOT add the port number in the 'Location' - header in the following cases: - - * A Location header that will use HTTP (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 80. - * A Location header that will use HTTPS (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 443. - - Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer scheme: - description: |- - Scheme is the scheme to be used in the value of the `Location` header in - the response. When empty, the scheme of the request is used. - - Scheme redirects can affect the port of the redirect, for more information, - refer to the documentation for the port field of this filter. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - Support: Extended enum: - http - https type: string statusCode: default: 302 - description: |- - StatusCode is the HTTP status code to be used in response. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - Support: Core enum: - 301 - 302 type: integer type: object responseHeaderModifier: - description: |- - ResponseHeaderModifier defines a schema for a filter that modifies response - headers. - - Support: Extended properties: add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - Input: - GET /foo HTTP/1.1 - my-header: foo - - Config: - add: - - name: "my-header" - value: "bar,baz" - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz items: - description: - HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: - description: - Value is the value of HTTP - Header to be matched. maxLength: 4096 minLength: 1 type: string @@ -1452,70 +1107,20 @@ spec: - name x-kubernetes-list-type: map remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - Config: - remove: ["my-header1", "my-header3"] - - Output: - GET /foo HTTP/1.1 - my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - Input: - GET /foo HTTP/1.1 - my-header: foo - - Config: - set: - - name: "my-header" - value: "bar" - - Output: - GET /foo HTTP/1.1 - my-header: bar items: - description: - HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: - description: - Value is the value of HTTP - Header to be matched. maxLength: 4096 minLength: 1 type: string @@ -1530,39 +1135,6 @@ spec: x-kubernetes-list-type: map type: object type: - description: |- - Type identifies the type of filter to apply. As with other API fields, - types are classified into three conformance levels: - - - Core: Filter types and their corresponding configuration defined by - "Support: Core" in this package, e.g. "RequestHeaderModifier". All - implementations must support core filters. - - - Extended: Filter types and their corresponding configuration defined by - "Support: Extended" in this package, e.g. "RequestMirror". Implementers - are encouraged to support extended filters. - - - Implementation-specific: Filters that are defined and supported by - specific vendors. - In the future, filters showing convergence in behavior across multiple - implementations will be considered for inclusion in extended or core - conformance levels. Filter-specific configuration for such filters - is specified using the ExtensionRef field. `Type` should be set to - "ExtensionRef" for custom filters. - - Implementers are encouraged to define custom implementation types to - extend the core API with implementation-specific behavior. - - If a reference to a custom filter type cannot be resolved, the filter - MUST NOT be skipped. Instead, requests that would have been processed by - that filter MUST receive a HTTP error response. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. enum: - RequestHeaderModifier - ResponseHeaderModifier @@ -1572,64 +1144,21 @@ spec: - ExtensionRef type: string urlRewrite: - description: |- - URLRewrite defines a schema for a filter that modifies a request during forwarding. - - Support: Extended properties: hostname: - description: |- - Hostname is the value to be used to replace the Host header value during - forwarding. - - Support: Extended maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: - description: |- - Path defines a path rewrite. - - Support: Extended properties: replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: - description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: - description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch @@ -1760,67 +1289,40 @@ spec: rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 - group: - default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Service - description: |- - Kind is the Kubernetes resource kind of the referent. For example - "Service". - - Defaults to "Service" when not specified. - - ExternalName services can refer to CNAME DNS records that may live - outside of the cluster and as such are difficult to reason about in - terms of conformance. They also may not be safe to forward to (see - CVE-2021-25740 for more information). Implementations SHOULD NOT - support ExternalName Services. - - Support: Core (Services with a type other than ExternalName) - - Support: Implementation-specific (Services with type ExternalName) - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the backend. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - port: - description: |- - Port specifies the destination port number to use for this resource. - Port is required when the referent is a Kubernetes Service. In this - case, the port number is the service port number, not the target port. - For other resources, destination port might be derived from the referent - resource or this field. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - + ref: + group: + default: "" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' canary: description: Metadata to add to the canary service type: object diff --git a/pkg/apis/flagger/v1beta1/canary.go b/pkg/apis/flagger/v1beta1/canary.go index 27c8c6943..7940dde1f 100644 --- a/pkg/apis/flagger/v1beta1/canary.go +++ b/pkg/apis/flagger/v1beta1/canary.go @@ -214,11 +214,11 @@ type CanaryService struct { // Primary is the metadata to add to the primary service // +optional - Primary *Custom `json:"primary,omitempty"` + Primary *CustomBackend `json:"primary,omitempty"` // Canary is the metadata to add to the canary service // +optional - Canary *Custom `json:"canary,omitempty"` + Canary *CustomBackend `json:"canary,omitempty"` } // CanaryAnalysis is used to describe how the analysis should be done @@ -497,14 +497,36 @@ type CustomMetadata struct { Annotations map[string]string `json:"annotations,omitempty"` } -// Custom holds labels, annotations, and proxyRef to set on generated objects. -type Custom struct { +// CustomBackend holds labels, annotations, and proxyRef to set on generated objects. +type CustomBackend struct { CustomMetadata - // BackendRef is a reference to a backend to forward matched requests to. + // Backend is a reference to a backend to forward matched requests to. // Defaults to the primary or canary service. // +optional - BackendRef *v1.HTTPBackendRef `json:"backendRef,omitempty"` + Backend *HTTPBackendRefTemplate `json:"backendRef,omitempty"` +} + +// HTTPBackendRefTemplate is a reference to a backend to forward matched requests to. +type HTTPBackendRefTemplate struct { + // Ref references a Kubernetes object. + BackendObjectReference *v1.BackendObjectReference `json:"ref,omitempty"` + + // Filters defined at this level should be executed if and only if the + // request is being forwarded to the backend defined here. + // + // Support: Implementation-specific (For broader support of filters, use the + // Filters field in HTTPRouteRule.) + // + // +optional + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:validation:XValidation:message="May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both",rule="!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" + // +kubebuilder:validation:XValidation:message="May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both",rule="!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" + // +kubebuilder:validation:XValidation:message="RequestHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1" + // +kubebuilder:validation:XValidation:message="ResponseHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1" + // +kubebuilder:validation:XValidation:message="RequestRedirect filter cannot be repeated",rule="self.filter(f, f.type == 'RequestRedirect').size() <= 1" + // +kubebuilder:validation:XValidation:message="URLRewrite filter cannot be repeated",rule="self.filter(f, f.type == 'URLRewrite').size() <= 1" + Filters []v1.HTTPRouteFilter `json:"filters,omitempty"` } // HTTPRewrite holds information about how to modify a request URI during diff --git a/pkg/apis/flagger/v1beta1/zz_generated.deepcopy.go b/pkg/apis/flagger/v1beta1/zz_generated.deepcopy.go index 82ac6f8af..24fd18ff3 100644 --- a/pkg/apis/flagger/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/flagger/v1beta1/zz_generated.deepcopy.go @@ -443,12 +443,12 @@ func (in *CanaryService) DeepCopyInto(out *CanaryService) { } if in.Primary != nil { in, out := &in.Primary, &out.Primary - *out = new(Custom) + *out = new(CustomBackend) (*in).DeepCopyInto(*out) } if in.Canary != nil { in, out := &in.Canary, &out.Canary - *out = new(Custom) + *out = new(CustomBackend) (*in).DeepCopyInto(*out) } return @@ -645,23 +645,23 @@ func (in *CrossNamespaceObjectReference) DeepCopy() *CrossNamespaceObjectReferen } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Custom) DeepCopyInto(out *Custom) { +func (in *CustomBackend) DeepCopyInto(out *CustomBackend) { *out = *in in.CustomMetadata.DeepCopyInto(&out.CustomMetadata) - if in.BackendRef != nil { - in, out := &in.BackendRef, &out.BackendRef - *out = new(gatewayapiv1.HTTPBackendRef) + if in.Backend != nil { + in, out := &in.Backend, &out.Backend + *out = new(HTTPBackendRefTemplate) (*in).DeepCopyInto(*out) } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Custom. -func (in *Custom) DeepCopy() *Custom { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomBackend. +func (in *CustomBackend) DeepCopy() *CustomBackend { if in == nil { return nil } - out := new(Custom) + out := new(CustomBackend) in.DeepCopyInto(out) return out } @@ -696,6 +696,34 @@ func (in *CustomMetadata) DeepCopy() *CustomMetadata { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPBackendRefTemplate) DeepCopyInto(out *HTTPBackendRefTemplate) { + *out = *in + if in.BackendObjectReference != nil { + in, out := &in.BackendObjectReference, &out.BackendObjectReference + *out = new(gatewayapiv1.BackendObjectReference) + (*in).DeepCopyInto(*out) + } + if in.Filters != nil { + in, out := &in.Filters, &out.Filters + *out = make([]gatewayapiv1.HTTPRouteFilter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPBackendRefTemplate. +func (in *HTTPBackendRefTemplate) DeepCopy() *HTTPBackendRefTemplate { + if in == nil { + return nil + } + out := new(HTTPBackendRefTemplate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPRewrite) DeepCopyInto(out *HTTPRewrite) { *out = *in diff --git a/pkg/router/gateway_api.go b/pkg/router/gateway_api.go index ed6c369cd..2c1a011ac 100644 --- a/pkg/router/gateway_api.go +++ b/pkg/router/gateway_api.go @@ -96,14 +96,8 @@ func (gwr *GatewayAPIRouter) Reconcile(canary *flaggerv1.Canary) error { Matches: matches, Filters: gwr.makeFilters(canary), BackendRefs: []v1.HTTPBackendRef{ - { - BackendRef: gwr.makeBackendRef(primarySvcName, initialPrimaryWeight, canary.Spec.Service.Port, &canary.Spec.Service.Primary.BackendRef.BackendRef), - Filters: canary.Spec.Service.Primary.BackendRef.Filters, - }, - { - BackendRef: gwr.makeBackendRef(canarySvcName, initialCanaryWeight, canary.Spec.Service.Port, &canary.Spec.Service.Canary.BackendRef.BackendRef), - Filters: canary.Spec.Service.Canary.BackendRef.Filters, - }, + gwr.makeHTTPBackendRef(primarySvcName, initialPrimaryWeight, canary.Spec.Service.Port, canary.Spec.Service.Primary), + gwr.makeHTTPBackendRef(canarySvcName, initialCanaryWeight, canary.Spec.Service.Port, canary.Spec.Service.Canary), }, }, }, @@ -124,10 +118,7 @@ func (gwr *GatewayAPIRouter) Reconcile(canary *flaggerv1.Canary) error { Matches: matches, Filters: gwr.makeFilters(canary), BackendRefs: []v1.HTTPBackendRef{ - { - BackendRef: gwr.makeBackendRef(primarySvcName, initialPrimaryWeight, canary.Spec.Service.Port, &canary.Spec.Service.Primary.BackendRef.BackendRef), - Filters: canary.Spec.Service.Primary.BackendRef.Filters, - }, + gwr.makeHTTPBackendRef(primarySvcName, initialPrimaryWeight, canary.Spec.Service.Port, canary.Spec.Service.Primary), }, }) if canary.Spec.Service.Timeout != "" { @@ -394,14 +385,8 @@ func (gwr *GatewayAPIRouter) SetRoutes( Matches: matches, Filters: gwr.makeFilters(canary), BackendRefs: []v1.HTTPBackendRef{ - { - BackendRef: gwr.makeBackendRef(primarySvcName, pWeight, canary.Spec.Service.Port, &canary.Spec.Service.Primary.BackendRef.BackendRef), - Filters: canary.Spec.Service.Primary.BackendRef.Filters, - }, - { - BackendRef: gwr.makeBackendRef(canarySvcName, cWeight, canary.Spec.Service.Port, &canary.Spec.Service.Canary.BackendRef.BackendRef), - Filters: canary.Spec.Service.Canary.BackendRef.Filters, - }, + gwr.makeHTTPBackendRef(primarySvcName, pWeight, canary.Spec.Service.Port, canary.Spec.Service.Primary), + gwr.makeHTTPBackendRef(canarySvcName, cWeight, canary.Spec.Service.Port, canary.Spec.Service.Canary), }, } if canary.Spec.Service.Timeout != "" { @@ -455,10 +440,7 @@ func (gwr *GatewayAPIRouter) SetRoutes( Matches: matches, Filters: gwr.makeFilters(canary), BackendRefs: []v1.HTTPBackendRef{ - { - BackendRef: gwr.makeBackendRef(primarySvcName, initialPrimaryWeight, canary.Spec.Service.Port, &canary.Spec.Service.Primary.BackendRef.BackendRef), - Filters: canary.Spec.Service.Primary.BackendRef.Filters, - }, + gwr.makeHTTPBackendRef(primarySvcName, initialPrimaryWeight, canary.Spec.Service.Port, canary.Spec.Service.Primary), }, Timeouts: &v1.HTTPRouteTimeouts{ Request: &timeout, @@ -541,14 +523,8 @@ func (gwr *GatewayAPIRouter) getSessionAffinityRouteRules(canary *flaggerv1.Cana mergedMatches := gwr.mergeMatchConditions([]v1.HTTPRouteMatch{cookieMatch}, svcMatches) stickyRouteRule.Matches = mergedMatches stickyRouteRule.BackendRefs = []v1.HTTPBackendRef{ - { - BackendRef: gwr.makeBackendRef(primarySvcName, 0, canary.Spec.Service.Port, &canary.Spec.Service.Primary.BackendRef.BackendRef), - Filters: canary.Spec.Service.Primary.BackendRef.Filters, - }, - { - BackendRef: gwr.makeBackendRef(canarySvcName, 100, canary.Spec.Service.Port, &canary.Spec.Service.Canary.BackendRef.BackendRef), - Filters: canary.Spec.Service.Canary.BackendRef.Filters, - }, + gwr.makeHTTPBackendRef(primarySvcName, 0, canary.Spec.Service.Port, canary.Spec.Service.Primary), + gwr.makeHTTPBackendRef(canarySvcName, 100, canary.Spec.Service.Port, canary.Spec.Service.Canary), } } else { // If canary weight is 0 and SessionAffinityCookie is non-blank, then it belongs to a previous canary run. @@ -671,21 +647,28 @@ func (gwr *GatewayAPIRouter) mapRouteMatches(requestMatches []istiov1beta1.HTTPM return matches, nil } -func (gwr *GatewayAPIRouter) makeBackendRef(svcName string, weight, port int32, backendRefTemplate *v1.BackendRef) v1.BackendRef { - if backendRefTemplate != nil { - backendRefTemplate.Weight = &weight - return *backendRefTemplate - } - - return v1.BackendRef{ - BackendObjectReference: v1.BackendObjectReference{ - Group: (*v1.Group)(&backendRefGroup), - Kind: (*v1.Kind)(&backendRefKind), - Name: v1.ObjectName(svcName), - Port: (*v1.PortNumber)(&port), +func (gwr *GatewayAPIRouter) makeHTTPBackendRef(svcName string, weight, port int32, customBackend *flaggerv1.CustomBackend) v1.HTTPBackendRef { + httpBackendRef := v1.HTTPBackendRef{ + BackendRef: v1.BackendRef{ + BackendObjectReference: v1.BackendObjectReference{ + Group: (*v1.Group)(&backendRefGroup), + Kind: (*v1.Kind)(&backendRefKind), + Name: v1.ObjectName(svcName), + Port: (*v1.PortNumber)(&port), + }, + Weight: &weight, }, - Weight: &weight, } + if customBackend != nil && customBackend.Backend != nil { + if customBackend.Backend.BackendObjectReference != nil { + httpBackendRef.BackendObjectReference = *customBackend.Backend.BackendObjectReference + } + if customBackend.Backend.Filters != nil { + httpBackendRef.Filters = customBackend.Backend.Filters + } + } + + return httpBackendRef } func (gwr *GatewayAPIRouter) mergeMatchConditions(analysis, service []v1.HTTPRouteMatch) []v1.HTTPRouteMatch { diff --git a/pkg/router/gateway_api_test.go b/pkg/router/gateway_api_test.go index d998c2da8..fb621f215 100644 --- a/pkg/router/gateway_api_test.go +++ b/pkg/router/gateway_api_test.go @@ -295,12 +295,8 @@ func TestGatewayAPIRouter_getSessionAffinityRouteRules(t *testing.T) { _, pSvcName, cSvcName := canary.GetServiceNames() weightedRouteRule := &v1.HTTPRouteRule{ BackendRefs: []v1.HTTPBackendRef{ - { - BackendRef: router.makeBackendRef(pSvcName, initialPrimaryWeight, canary.Spec.Service.Port, &canary.Spec.Service.Primary.BackendRef.BackendRef), - }, - { - BackendRef: router.makeBackendRef(cSvcName, initialCanaryWeight, canary.Spec.Service.Port, &canary.Spec.Service.Canary.BackendRef.BackendRef), - }, + router.makeHTTPBackendRef(pSvcName, initialPrimaryWeight, canary.Spec.Service.Port, canary.Spec.Service.Primary), + router.makeHTTPBackendRef(cSvcName, initialCanaryWeight, canary.Spec.Service.Port, canary.Spec.Service.Canary), }, } rules, err := router.getSessionAffinityRouteRules(canary, 10, weightedRouteRule) diff --git a/pkg/router/kubernetes_default.go b/pkg/router/kubernetes_default.go index 7aa5484c7..f5623f15f 100644 --- a/pkg/router/kubernetes_default.go +++ b/pkg/router/kubernetes_default.go @@ -50,13 +50,21 @@ func (c *KubernetesDefaultRouter) Initialize(canary *flaggerv1.Canary) error { _, primaryName, canaryName := canary.GetServiceNames() // canary svc - err := c.reconcileService(canary, canaryName, c.labelValue, &canary.Spec.Service.Canary.CustomMetadata) + canaryCustomMetadata := &flaggerv1.CustomMetadata{} + if canary.Spec.Service.Canary != nil { + canaryCustomMetadata = &canary.Spec.Service.Canary.CustomMetadata + } + err := c.reconcileService(canary, canaryName, c.labelValue, canaryCustomMetadata) if err != nil { return fmt.Errorf("reconcileService failed: %w", err) } // primary svc - err = c.reconcileService(canary, primaryName, fmt.Sprintf("%s-primary", c.labelValue), &canary.Spec.Service.Primary.CustomMetadata) + primaryCustomMetadata := &flaggerv1.CustomMetadata{} + if canary.Spec.Service.Primary != nil { + primaryCustomMetadata = &canary.Spec.Service.Primary.CustomMetadata + } + err = c.reconcileService(canary, primaryName, fmt.Sprintf("%s-primary", c.labelValue), primaryCustomMetadata) if err != nil { return fmt.Errorf("reconcileService failed: %w", err) } diff --git a/pkg/router/kubernetes_default_test.go b/pkg/router/kubernetes_default_test.go index 2b5a82553..4d7ed4122 100644 --- a/pkg/router/kubernetes_default_test.go +++ b/pkg/router/kubernetes_default_test.go @@ -375,7 +375,7 @@ func TestServiceRouter_InitializeMetadata(t *testing.T) { labelSelector: "app", } - mocks.canary.Spec.Service.Canary = &flaggerv1.Custom{ + mocks.canary.Spec.Service.Canary = &flaggerv1.CustomBackend{ CustomMetadata: flaggerv1.CustomMetadata{ Labels: map[string]string{"test": "test"}, Annotations: map[string]string{"test": "test"},