From 8e32d1913b838cabd4c344ca3c1463500d163c6b Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Tue, 9 Nov 2021 11:34:06 +0100 Subject: [PATCH] Update gateway api provider to v1alpha2 Co-authored-by: Tom Moulard --- docs/content/migration/v2.md | 8 +- docs/content/providers/kubernetes-gateway.md | 20 +- ...way.networking.k8s.io_gatewayclasses.yaml} | 76 +- ...> gateway.networking.k8s.io_gateways.yaml} | 592 ++-- .../gateway.networking.k8s.io_httproutes.yaml | 1284 +++++++ .../gateway.networking.k8s.io_tcproutes.yaml | 431 +++ .../gateway.networking.k8s.io_tlsroutes.yaml | 480 +++ .../kubernetes-gateway-rbac.yml | 5 +- .../kubernetes-gateway-resource.yml | 130 +- .../kubernetes-gateway-simple-https.yml | 42 +- .../kubernetes-gateway-traefik-lb-svc.yml | 14 +- .../kubernetes-gateway.md | 10 +- .../kubernetes-whoami-svc.yml | 9 +- .../networking.x-k8s.io_httproutes.yaml | 971 ----- .../networking.x-k8s.io_tcproutes.yaml | 401 --- .../networking.x-k8s.io_tlsroutes.yaml | 437 --- .../routing/providers/kubernetes-gateway.md | 366 +- go.mod | 16 +- go.sum | 290 +- .../fixtures/k8s/01-gateway-api-crd.yml | 3140 +++++++++++++++++ integration/fixtures/k8s/01-gateway-api.yml | 2710 -------------- integration/fixtures/k8s/03-gateway.yml | 120 +- integration/testdata/rawdata-gateway.json | 12 +- pkg/provider/kubernetes/gateway/client.go | 87 +- .../kubernetes/gateway/client_mock_test.go | 52 +- .../kubernetes/gateway/client_test.go | 84 +- .../gatewayclass_with_unknown_controller.yml | 25 +- .../httproute/one_rule_two_targets.yml | 35 +- .../gateway/fixtures/httproute/simple.yml | 34 +- .../httproute/simple_cross_provider.yml | 39 +- .../httproute/simple_to_api_internal.yml | 34 +- .../httproute/simple_with_bad_rule.yml | 31 +- .../httproute/simple_with_tls_entrypoint.yml | 29 +- .../gateway/fixtures/httproute/two_rules.yml | 37 +- .../fixtures/httproute/with_multiple_host.yml | 31 +- .../fixtures/httproute/with_namespace_all.yml | 46 +- .../httproute/with_namespace_same.yml | 41 +- .../httproute/with_namespace_selector.yml | 46 +- .../httproute/with_protocol_https.yml | 39 +- ...th_protocol_https_with_tls_passthrough.yml | 32 +- .../with_protocol_https_without_tls.yml | 25 +- .../fixtures/httproute/with_protocol_tcp.yml | 25 +- .../fixtures/httproute/with_protocol_tls.yml | 32 +- .../fixtures/httproute/with_several_rules.yml | 55 +- .../httproute/with_tls_configuration.yml | 24 + .../with_two_gateways_one_httproute.yml | 55 +- .../with_two_listeners_one_httproute.yml | 49 +- .../httproute/with_wrong_service_port.yml | 29 +- .../httproute/without_gatewayclass.yml | 21 +- .../fixtures/httproute/without_httproute.yml | 18 +- .../gateway/fixtures/mixed/simple.yml | 141 +- .../mixed/with_bad_listener_protocol.yml | 28 +- .../mixed/with_bad_listener_route_kind.yml | 28 +- .../fixtures/mixed/with_core_group.yml | 135 + ...h_incompatible_protocol_and_route_kind.yml | 28 +- ...with_multiple_protocol_using_same_port.yml | 116 +- .../fixtures/mixed/with_namespace_all.yml | 199 +- .../fixtures/mixed/with_namespace_same.yml | 199 +- .../mixed/with_namespace_selector.yml | 211 +- .../mixed/with_wrong_routes_selector.yml | 84 +- .../gatewayclass_with_unknown_controller.yml | 30 +- .../gateway/fixtures/tcproute/simple.yml | 36 +- .../tcproute/simple_cross_provider.yml | 41 +- .../tcproute/with_multiple_routes.yml | 67 +- .../fixtures/tcproute/with_multiple_rules.yml | 42 +- .../fixtures/tcproute/with_namespace_all.yml | 51 +- .../fixtures/tcproute/with_namespace_same.yml | 51 +- .../tcproute/with_namespace_selector.yml | 49 +- .../fixtures/tcproute/with_protocol_http.yml | 25 +- .../fixtures/tcproute/with_protocol_https.yml | 32 +- .../fixtures/tcproute/with_protocol_tls.yml | 42 +- .../tcproute/with_tls_configuration.yml | 26 + .../tcproute/with_wrong_service_port.yml | 30 +- .../tcproute/without_gatewayclass.yml | 26 +- .../fixtures/tcproute/without_tcproute.yml | 20 +- .../without_tcproute_tls_protocol.yml | 26 +- .../gatewayclass_with_unknown_controller.yml | 38 +- .../tlsroute/simple_TLS_to_TCPRoute.yml | 44 +- .../simple_TLS_to_TCPRoute_passthrough.yml | 49 + ...le_TLS_to_TCPRoute_with_certificateRef.yml | 57 - .../tlsroute/simple_TLS_to_TLSRoute.yml | 36 +- .../tlsroute/simple_cross_provider.yml | 49 +- .../fixtures/tlsroute/with_SNI_matching.yml | 42 +- .../tlsroute/with_invalid_SNI_matching.yml | 42 +- .../tlsroute/with_multiple_SNI_matching.yml | 44 +- .../tlsroute/with_multiple_routes_kind.yml | 73 +- .../fixtures/tlsroute/with_multiple_rules.yml | 54 + .../fixtures/tlsroute/with_namespace_all.yml | 61 +- .../fixtures/tlsroute/with_namespace_same.yml | 59 +- .../tlsroute/with_namespace_selector.yml | 60 +- .../fixtures/tlsroute/with_passthrough.yml | 34 +- .../tlsroute/with_passthrough_tls.yml | 42 +- .../fixtures/tlsroute/with_protocol_http.yml | 25 +- .../fixtures/tlsroute/with_protocol_https.yml | 32 +- .../fixtures/tlsroute/with_protocol_tcp.yml | 25 +- .../tlsroute/with_wrong_service_port.yml | 42 +- .../tlsroute/without_gatewayclass.yml | 26 +- .../fixtures/tlsroute/without_tlsroute.yml | 20 +- .../fixtures/with_two_hosts_one_wildcard.yml | 30 +- .../fixtures/with_two_hosts_wildcard.yml | 32 +- pkg/provider/kubernetes/gateway/kubernetes.go | 1149 +++--- .../kubernetes/gateway/kubernetes_test.go | 1572 +++++++-- 102 files changed, 10330 insertions(+), 7789 deletions(-) rename docs/content/reference/dynamic-configuration/{networking.x-k8s.io_gatewayclasses.yaml => gateway.networking.k8s.io_gatewayclasses.yaml} (76%) rename docs/content/reference/dynamic-configuration/{networking.x-k8s.io_gateways.yaml => gateway.networking.k8s.io_gateways.yaml} (52%) create mode 100644 docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_httproutes.yaml create mode 100644 docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tcproutes.yaml create mode 100644 docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tlsroutes.yaml delete mode 100644 docs/content/reference/dynamic-configuration/networking.x-k8s.io_httproutes.yaml delete mode 100644 docs/content/reference/dynamic-configuration/networking.x-k8s.io_tcproutes.yaml delete mode 100644 docs/content/reference/dynamic-configuration/networking.x-k8s.io_tlsroutes.yaml create mode 100644 integration/fixtures/k8s/01-gateway-api-crd.yml delete mode 100644 integration/fixtures/k8s/01-gateway-api.yml create mode 100644 pkg/provider/kubernetes/gateway/fixtures/httproute/with_tls_configuration.yml create mode 100644 pkg/provider/kubernetes/gateway/fixtures/mixed/with_core_group.yml create mode 100644 pkg/provider/kubernetes/gateway/fixtures/tcproute/with_tls_configuration.yml create mode 100644 pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute_passthrough.yml delete mode 100644 pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute_with_certificateRef.yml create mode 100644 pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_rules.yml diff --git a/docs/content/migration/v2.md b/docs/content/migration/v2.md index ec772d7da..e055fe120 100644 --- a/docs/content/migration/v2.md +++ b/docs/content/migration/v2.md @@ -433,8 +433,8 @@ which allows advertising, in the `Alt-Svc` header, a UDP port different from the By doing so, it introduces a new configuration structure `http3`, which replaces the `enableHTTP3` option (which therefore doesn't exist anymore). To enable HTTP3 on an EntryPoint, please check out the [HTTP3 configuration](../routing/entrypoints.md#http3) documentation. -### Kubernetes Gateway provider +### Kubernetes Gateway API Provider -In `v2.6`, the [Kubernetes Gateway provider](../providers/kubernetes-gateway.md) now supports [route namespaces](https://gateway-api.sigs.k8s.io/v1alpha1/references/spec/#networking.x-k8s.io/v1alpha1.RouteNamespaces) selectors, -which requires Traefik to fetch and watch the cluster namespaces. -Therefore, the RBAC definitions must be updated, please check out the [RBAC configuration reference](../reference/dynamic-configuration/kubernetes-gateway.md#rbac). +In `v2.6`, the [Kubernetes Gateway API provider](../providers/kubernetes-gateway.md) now only supports the version [v1alpha2](https://gateway-api.sigs.k8s.io/v1alpha2/guides/getting-started/) of the specification and +[route namespaces](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.RouteNamespaces) selectors, which requires Traefik to fetch and watch the cluster namespaces. +Therefore, the [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) and [CRD](../reference/dynamic-configuration/kubernetes-gateway.md#definitions) definitions must be updated. diff --git a/docs/content/providers/kubernetes-gateway.md b/docs/content/providers/kubernetes-gateway.md index bc38cbb40..d9cbe1d60 100644 --- a/docs/content/providers/kubernetes-gateway.md +++ b/docs/content/providers/kubernetes-gateway.md @@ -9,7 +9,7 @@ The Gateway API project is part of Kubernetes, working under SIG-NETWORK. The Kubernetes Gateway provider is a Traefik implementation of the [Gateway API](https://gateway-api.sigs.k8s.io/) specifications from the Kubernetes Special Interest Groups (SIGs). -This provider is proposed as an experimental feature and partially supports the Gateway API [v0.3.0](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v0.3.0) specification. +This provider is proposed as an experimental feature and partially supports the Gateway API [v0.4.0](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v0.4.0) specification. !!! warning "Enabling The Experimental Kubernetes Gateway Provider" @@ -41,7 +41,7 @@ This provider is proposed as an experimental feature and partially supports the !!! tip "All Steps for a Successful Deployment" * Add/update the Kubernetes Gateway API [definitions](../reference/dynamic-configuration/kubernetes-gateway.md#definitions). - * Add/update the [RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) for the Traefik custom resources. + * Add/update the [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) for the Traefik custom resources. * Add all needed Kubernetes Gateway API [resources](../reference/dynamic-configuration/kubernetes-gateway.md#resources). ## Examples @@ -62,9 +62,9 @@ This provider is proposed as an experimental feature and partially supports the ```yaml tab="Gateway API CRDs" # All resources definition must be declared - --8<-- "content/reference/dynamic-configuration/networking.x-k8s.io_gatewayclasses.yaml" - --8<-- "content/reference/dynamic-configuration/networking.x-k8s.io_gateways.yaml" - --8<-- "content/reference/dynamic-configuration/networking.x-k8s.io_httproutes.yaml" + --8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_gatewayclasses.yaml" + --8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_gateways.yaml" + --8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_httproutes.yaml" ``` ```yaml tab="RBAC" @@ -73,17 +73,17 @@ This provider is proposed as an experimental feature and partially supports the The Kubernetes Gateway API project provides several guides on how to use the APIs. These guides can help you to go further than the example above. -The [getting started guide](https://gateway-api.sigs.k8s.io/v1alpha1/guides/getting-started/) details how to install the CRDs from their repository. +The [getting started guide](https://gateway-api.sigs.k8s.io/v1alpha2/guides/getting-started/) details how to install the CRDs from their repository. !!! note "" - Keep in mind that the Traefik Gateway provider only supports the `v0.3.0` (v1alpha1). + Keep in mind that the Traefik Gateway provider only supports the `v0.4.0` (v1alpha2). For now, the Traefik Gateway Provider can be used while following the below guides: -* [Simple Gateway](https://gateway-api.sigs.k8s.io/v1alpha1/guides/simple-gateway/) -* [HTTP routing](https://gateway-api.sigs.k8s.io/v1alpha1/guides/http-routing/) -* [TLS](https://gateway-api.sigs.k8s.io/v1alpha1/guides/tls/) +* [Simple Gateway](https://gateway-api.sigs.k8s.io/v1alpha2/guides/simple-gateway/) +* [HTTP routing](https://gateway-api.sigs.k8s.io/v1alpha2/guides/http-routing/) +* [TLS](https://gateway-api.sigs.k8s.io/v1alpha2/guides/tls/) ## Resource Configuration diff --git a/docs/content/reference/dynamic-configuration/networking.x-k8s.io_gatewayclasses.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gatewayclasses.yaml similarity index 76% rename from docs/content/reference/dynamic-configuration/networking.x-k8s.io_gatewayclasses.yaml rename to docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gatewayclasses.yaml index 5872e7ec7..cac5b0ee7 100644 --- a/docs/content/reference/dynamic-configuration/networking.x-k8s.io_gatewayclasses.yaml +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gatewayclasses.yaml @@ -4,11 +4,11 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.5.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 creationTimestamp: null - name: gatewayclasses.networking.x-k8s.io + name: gatewayclasses.gateway.networking.k8s.io spec: - group: networking.x-k8s.io + group: gateway.networking.k8s.io names: categories: - gateway-api @@ -27,12 +27,26 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1alpha1 + - jsonPath: .spec.description + name: Description + priority: 1 + type: string + name: v1alpha2 schema: openAPIV3Schema: description: "GatewayClass describes a class of Gateways available to the - user for creating Gateway resources. \n GatewayClass is a Cluster level - resource." + user for creating Gateway resources. \n It is recommended that this resource + be used as a template for Gateways. This means that a Gateway is based on + the state of the GatewayClass at the time it was created and changes to + the GatewayClass or associated parameters are not propagated down to existing + Gateways. This recommendation is intended to limit the blast radius of changes + to GatewayClass or associated parameters. If implementations choose to propagate + GatewayClass changes to existing Gateways, that MUST be clearly documented + by the implementation. \n Whenever one or more Gateways are using a GatewayClass, + implementations MUST add the `gateway-exists-finalizer.gateway.networking.k8s.io` + finalizer on the associated GatewayClass. This ensures that a GatewayClass + associated with a Gateway is not deleted while in use. \n GatewayClass is + a Cluster level resource." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -49,14 +63,18 @@ spec: spec: description: Spec defines the desired state of GatewayClass. properties: - controller: - description: "Controller is a domain/path string that indicates the - controller that is managing Gateways of this class. \n Example: - \"acme.io/gateway-controller\". \n This field is not mutable and - cannot be empty. \n The format of this field is DOMAIN \"/\" PATH, - where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). - \n Support: Core" + controllerName: + description: "ControllerName is the name of the controller that is + managing Gateways of this class. The value of this field MUST be + a domain prefixed path. \n Example: \"example.net/gateway-controller\". + \n This field is not mutable and cannot be empty. \n 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])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + description: + description: Description helps describe a GatewayClass with more details. + maxLength: 64 type: string parametersRef: description: "ParametersRef is a reference to a resource that contains @@ -71,12 +89,13 @@ spec: group: description: Group is the group of the referent. 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 kind: description: Kind is kind of the referent. - maxLength: 253 + 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. @@ -85,18 +104,11 @@ spec: type: string namespace: description: Namespace is the namespace of the referent. This - field is required when scope is set to "Namespace" and ignored - when scope is set to "Cluster". - maxLength: 253 + field is required when referring to a Namespace-scoped resource + and MUST be unset when referring to a Cluster-scoped resource. + maxLength: 63 minLength: 1 - type: string - scope: - default: Cluster - description: Scope represents if the referent is a Cluster or - Namespace scoped resource. This may be set to "Cluster" or "Namespace". - enum: - - Cluster - - Namespace + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string required: - group @@ -104,7 +116,7 @@ spec: - name type: object required: - - controller + - controllerName type: object status: default: @@ -112,8 +124,8 @@ spec: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Waiting - status: "False" - type: Admitted + status: Unknown + type: Accepted description: Status defines the current state of GatewayClass. properties: conditions: @@ -121,8 +133,8 @@ spec: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Waiting - status: "False" - type: Admitted + status: Unknown + type: Accepted description: "Conditions is the current status from the controller for this GatewayClass. \n Controllers should prefer to publish conditions using values of GatewayClassConditionType for the type of each Condition." @@ -199,6 +211,8 @@ spec: - type x-kubernetes-list-type: map type: object + required: + - spec type: object served: true storage: true diff --git a/docs/content/reference/dynamic-configuration/networking.x-k8s.io_gateways.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gateways.yaml similarity index 52% rename from docs/content/reference/dynamic-configuration/networking.x-k8s.io_gateways.yaml rename to docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gateways.yaml index 25eca95a7..486471336 100644 --- a/docs/content/reference/dynamic-configuration/networking.x-k8s.io_gateways.yaml +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gateways.yaml @@ -4,11 +4,11 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.5.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 creationTimestamp: null - name: gateways.networking.x-k8s.io + name: gateways.gateway.networking.k8s.io spec: - group: networking.x-k8s.io + group: gateway.networking.k8s.io names: categories: - gateway-api @@ -24,18 +24,20 @@ spec: - jsonPath: .spec.gatewayClassName name: Class type: string + - jsonPath: .status.addresses[*].value + name: Address + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1alpha1 + name: v1alpha2 schema: openAPIV3Schema: - description: "Gateway represents an instantiation of a service-traffic handling - infrastructure by binding Listeners to a set of IP addresses. \n Implementations - should add the `gateway-exists-finalizer.networking.x-k8s.io` finalizer - on the associated GatewayClass whenever Gateway(s) is running. This ensures - that a GatewayClass associated with a Gateway(s) is not deleted while in - use." + description: Gateway represents an instance of a service-traffic handling + infrastructure by binding Listeners to a set of IP addresses. properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -53,24 +55,32 @@ spec: description: Spec defines the desired state of Gateway. properties: addresses: - description: "Addresses requested for this gateway. This is optional - and behavior can depend on the GatewayClass. If a value is set in - the spec and the requested address is invalid, the GatewayClass - MUST indicate this in the associated entry in GatewayStatus.Addresses. - \n If no Addresses are specified, the GatewayClass may schedule - the Gateway in an implementation-defined manner, assigning an appropriate - set of Addresses. \n The GatewayClass MUST bind all Listeners to - every GatewayAddress that it assigns to the Gateway. \n Support: - Core" + description: "Addresses requested for this Gateway. This is optional + and behavior can depend on the implementation. If a value is set + in the spec and the requested address is invalid or unavailable, + the implementation MUST indicate this in the associated entry in + GatewayStatus.Addresses. \n The Addresses field represents a request + for the address(es) on the \"outside of the Gateway\", that traffic + bound for this Gateway will use. This could be the IP address or + hostname of an external load balancer or other networking infrastructure, + or some other address that traffic will be sent to. \n The .listener.hostname + field is used to route traffic that has already arrived at the Gateway + to the correct in-cluster destination. \n If no Addresses are specified, + the implementation MAY schedule the Gateway in an implementation-specific + manner, assigning an appropriate set of Addresses. \n The implementation + MUST bind all Listeners to every GatewayAddress that it assigns + to the Gateway and add a corresponding entry in GatewayStatus.Addresses. + \n Support: Core" items: description: GatewayAddress describes an address that can be bound to a Gateway. properties: type: default: IPAddress - description: "Type of the address. \n Support: Extended" + description: Type of the address. enum: - IPAddress + - Hostname - NamedAddress type: string value: @@ -94,130 +104,96 @@ spec: listeners: description: "Listeners associated with this Gateway. Listeners define logical endpoints that are bound on this Gateway's addresses. At - least one Listener MUST be specified. \n An implementation MAY group - Listeners by Port and then collapse each group of Listeners into - a single Listener if the implementation determines that the Listeners - in the group are \"compatible\". An implementation MAY also group - together and collapse compatible Listeners belonging to different - Gateways. \n For example, an implementation might consider Listeners - to be compatible with each other if all of the following conditions - are met: \n 1. Either each Listener within the group specifies the - \"HTTP\" Protocol or each Listener within the group specifies - either the \"HTTPS\" or \"TLS\" Protocol. \n 2. Each Listener - within the group specifies a Hostname that is unique within the - group. \n 3. As a special case, one Listener within a group may - omit Hostname, in which case this Listener matches when no other - Listener matches. \n If the implementation does collapse compatible - Listeners, the hostname provided in the incoming client request - MUST be matched to a Listener to find the correct set of Routes. - The incoming hostname MUST be matched using the Hostname field for - each Listener in order of most to least specific. That is, exact - matches must be processed before wildcard matches. \n If this field - specifies multiple Listeners that have the same Port value but are - not compatible, the implementation must raise a \"Conflicted\" condition - in the Listener status. \n Support: Core" + least one Listener MUST be specified. \n Each listener in a Gateway + must have a unique combination of Hostname, Port, and Protocol. + \n An implementation MAY group Listeners by Port and then collapse + each group of Listeners into a single Listener if the implementation + determines that the Listeners in the group are \"compatible\". An + implementation MAY also group together and collapse compatible Listeners + belonging to different Gateways. \n For example, an implementation + might consider Listeners to be compatible with each other if all + of the following conditions are met: \n 1. Either each Listener + within the group specifies the \"HTTP\" Protocol or each Listener + within the group specifies either the \"HTTPS\" or \"TLS\" Protocol. + \n 2. Each Listener within the group specifies a Hostname that is + unique within the group. \n 3. As a special case, one Listener + within a group may omit Hostname, in which case this Listener + matches when no other Listener matches. \n If the implementation + does collapse compatible Listeners, the hostname provided in the + incoming client request MUST be matched to a Listener to find the + correct set of Routes. The incoming hostname MUST be matched using + the Hostname field for each Listener in order of most to least specific. + That is, exact matches must be processed before wildcard matches. + \n If this field specifies multiple Listeners that have the same + Port value but are not compatible, the implementation must raise + a \"Conflicted\" condition in the Listener status. \n Support: Core" items: description: Listener embodies the concept of a logical endpoint - where a Gateway can accept network connections. Each listener - in a Gateway must have a unique combination of Hostname, Port, - and Protocol. This will be enforced by a validating webhook. + where a Gateway accepts network connections. properties: - hostname: - description: "Hostname specifies the virtual hostname to match - for protocol types that define this concept. When unspecified, - \"\", or `*`, all hostnames are matched. This field can be - omitted for protocols that don't require hostname based matching. - \n Hostname is the fully qualified domain name of a network - host, as defined by RFC 3986. Note the following deviations - from the \"host\" part of the URI as defined in the RFC: \n - 1. IP literals are not allowed. 2. The `:` delimiter is not - respected because ports are not allowed. \n Hostname can be - \"precise\" which is a domain name without the terminating - dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", - which is a domain name prefixed with a single wildcard label - (e.g. `*.example.com`). The wildcard character `*` must appear - by itself as the first DNS label and matches only a single - label. \n Support: Core" - maxLength: 253 - minLength: 1 - type: string - port: - description: "Port is the network port. Multiple listeners may - use the same port, subject to the Listener compatibility rules. + allowedRoutes: + default: + namespaces: + from: Same + description: "AllowedRoutes defines the types of routes that + MAY be attached to a Listener and the trusted namespaces where + those Route resources MAY be present. \n Although a client + request may match multiple route rules, only one rule may + ultimately receive the request. Matching precedence MUST be + determined in order of the following criteria: \n * The most + specific match as defined by the Route type. * The oldest + Route based on creation timestamp. For example, a Route with + \ a creation timestamp of \"2020-09-08 01:02:03\" is given + precedence over a Route with a creation timestamp of \"2020-09-08 + 01:02:04\". * If everything else is equivalent, the Route + appearing first in alphabetical order (namespace/name) should + be given precedence. For example, foo/bar is given precedence + over foo/baz. \n All valid rules within a Route attached to + this Listener should be implemented. Invalid Route rules can + be ignored (sometimes that will mean the full Route). If a + Route rule transitions from valid to invalid, support for + that Route rule should be dropped to ensure consistency. For + example, even if a filter specified by a Route rule is invalid, + the rest of the rules within that Route should still be supported. \n Support: Core" - format: int32 - maximum: 65535 - minimum: 1 - type: integer - protocol: - description: "Protocol specifies the network protocol this listener - expects to receive. The GatewayClass MUST apply the Hostname - match appropriately for each protocol: \n * For the \"TLS\" - protocol, the Hostname match MUST be applied to the [SNI](https://tools.ietf.org/html/rfc6066#section-3) - \ server name offered by the client. * For the \"HTTP\" protocol, - the Hostname match MUST be applied to the host portion of - the [effective request URI](https://tools.ietf.org/html/rfc7230#section-5.5) - \ or the [:authority pseudo-header](https://tools.ietf.org/html/rfc7540#section-8.1.2.3) - * For the \"HTTPS\" protocol, the Hostname match MUST be applied - at both the TLS and HTTP protocol layers. \n Support: Core" - type: string - routes: - description: "Routes specifies a schema for associating routes - with the Listener using selectors. A Route is a resource capable - of servicing a request and allows a cluster operator to expose - a cluster resource (i.e. Service) by externally-reachable - URL, load-balance traffic and terminate SSL/TLS. Typically, - a route is a \"HTTPRoute\" or \"TCPRoute\" in group \"networking.x-k8s.io\", - however, an implementation may support other types of resources. - \n The Routes selector MUST select a set of objects that are - compatible with the application protocol specified in the - Protocol field. \n Although a client request may technically - match multiple route rules, only one rule may ultimately receive - the request. Matching precedence MUST be determined in order - of the following criteria: \n * The most specific match. For - example, the most specific HTTPRoute match is determined - by the longest matching combination of hostname and path. - * The oldest Route based on creation timestamp. For example, - a Route with a creation timestamp of \"2020-09-08 01:02:03\" - is given precedence over a Route with a creation timestamp - of \"2020-09-08 01:02:04\". * If everything else is equivalent, - the Route appearing first in alphabetical order (namespace/name) - should be given precedence. For example, foo/bar is given - precedence over foo/baz. \n All valid portions of a Route - selected by this field should be supported. Invalid portions - of a Route can be ignored (sometimes that will mean the full - Route). If a portion of a Route transitions from valid to - invalid, support for that portion of the Route should be dropped - to ensure consistency. For example, even if a filter specified - by a Route is invalid, the rest of the Route should still - be supported. \n Support: Core" properties: - group: - default: networking.x-k8s.io - description: "Group is the group of the route resource to - select. Omitting the value or specifying the empty string - indicates the networking.x-k8s.io API group. For example, - use the following to select an HTTPRoute: \n routes: kind: - HTTPRoute \n Otherwise, if an alternative API group is - desired, specify the desired group: \n routes: group: - acme.io kind: FooRoute \n Support: Core" - maxLength: 253 - minLength: 1 - type: string - kind: - description: "Kind is the kind of the route resource to - select. \n Kind MUST correspond to kinds of routes that - are compatible with the application protocol specified - in the Listener's Protocol field. \n If an implementation - does not support or recognize this resource type, it SHOULD - set the \"ResolvedRefs\" condition to false for this listener - with the \"InvalidRoutesRef\" reason. \n Support: Core" - type: string + kinds: + description: "Kinds specifies the groups and kinds of Routes + that are allowed to bind to this Gateway Listener. When + unspecified or empty, the kinds of Routes selected are + determined using the Listener protocol. \n A RouteGroupKind + MUST correspond to kinds of Routes that are compatible + with the application protocol specified in the Listener's + Protocol field. If an implementation does not support + or recognize this resource type, it MUST set the \"ResolvedRefs\" + condition to False for this Listener with the \"InvalidRoutesRef\" + reason. \n Support: Core" + items: + description: RouteGroupKind indicates the group and kind + of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + 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 the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array namespaces: default: from: Same - description: "Namespaces indicates in which namespaces Routes - should be selected for this Gateway. This is restricted + description: "Namespaces indicates namespaces from which + Routes may be attached to this Listener. This is restricted to the namespace of this Gateway by default. \n Support: Core" properties: @@ -286,156 +262,180 @@ spec: type: object type: object type: object - selector: - description: "Selector specifies a set of route labels used - for selecting routes to associate with the Gateway. If - this Selector is defined, only routes matching the Selector - are associated with the Gateway. An empty Selector matches - all routes. \n Support: Core" - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. - If the operator is In or NotIn, the values array - must be non-empty. If the operator is Exists - or DoesNotExist, the values array must be empty. - This array is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. - A single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field - is "key", the operator is "In", and the values array - contains only "value". The requirements are ANDed. - type: object - type: object - required: - - kind type: object + hostname: + description: "Hostname specifies the virtual hostname to match + for protocol types that define this concept. When unspecified, + all hostnames are matched. This field is ignored for protocols + that don't require hostname based matching. \n Implementations + MUST apply Hostname matching appropriately for each of the + following protocols: \n * TLS: The Listener Hostname MUST + match the SNI. * HTTP: The Listener Hostname MUST match the + Host header of the request. * HTTPS: The Listener Hostname + SHOULD match at both the TLS and HTTP protocol layers as + described above. If an implementation does not ensure that + both the SNI and Host header match the Listener hostname, + \ it MUST clearly document that. \n For HTTPRoute and TLSRoute + resources, there is an interaction with the `spec.hostnames` + array. When both listener and route specify hostnames, there + MUST be an intersection between the values for a Route to + be accepted. For more information, refer to the Route specific + Hostnames documentation. \n 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 + name: + description: "Name is the name of the Listener. \n 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 + port: + description: "Port is the network port. Multiple listeners may + use the same port, subject to the Listener compatibility rules. + \n Support: Core" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: "Protocol specifies the network protocol this listener + expects to receive. \n Support: Core" + maxLength: 255 + minLength: 1 + pattern: ^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ + type: string tls: description: "TLS is the TLS configuration for the Listener. This field is required if the Protocol field is \"HTTPS\" - or \"TLS\" and ignored otherwise. \n The association of SNIs - to Certificate defined in GatewayTLSConfig is defined based - on the Hostname field for this listener. \n The GatewayClass + or \"TLS\". It is invalid to set this field if the Protocol + field is \"HTTP\", \"TCP\", or \"UDP\". \n The association + of SNIs to Certificate defined in GatewayTLSConfig is defined + based on the Hostname field for this listener. \n The GatewayClass MUST use the longest matching SNI out of all available certificates for any TLS handshake. \n Support: Core" properties: - certificateRef: - description: "CertificateRef is a reference to a Kubernetes - object that contains a TLS certificate and private key. - This certificate is used to establish a TLS handshake - for requests that match the hostname of the associated - listener. The referenced object MUST reside in the same - namespace as Gateway. \n This field is required when mode - is set to \"Terminate\" (default) and optional otherwise. - \n CertificateRef can reference a standard Kubernetes - resource, i.e. Secret, or an implementation-specific custom - resource. \n Support: Core (Kubernetes Secrets) \n Support: - Implementation-specific (Other resource types)" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object + certificateRefs: + description: "CertificateRefs contains a series of references + to Kubernetes objects that contains TLS certificates and + private keys. These certificates are used to establish + a TLS handshake for requests that match the hostname of + the associated listener. \n A single CertificateRef to + a Kubernetes Secret has \"Core\" support. Implementations + MAY choose to support attaching multiple certificates + to a Listener, but this behavior is implementation-specific. + \n References to a resource in different namespace are + invalid UNLESS there is a ReferencePolicy in the target + namespace that allows the certificate to be attached. + If a ReferencePolicy does not allow this reference, the + \"ResolvedRefs\" condition MUST be set to False for this + listener with the \"InvalidCertificateRef\" reason. \n + This field is required to have at least one element when + the mode is set to \"Terminate\" (default) and is optional + otherwise. \n CertificateRefs can reference to standard + Kubernetes resources, i.e. Secret, or implementation-specific + custom resources. \n Support: Core - A single reference + to a Kubernetes Secret \n Support: Implementation-specific + (More than one reference or other resource types)" + items: + description: "SecretObjectReference identifies an API + object including its namespace, defaulting to Secret. + \n The API object must be valid in the cluster; the + Group and Kind must be registered in the cluster for + this reference to be valid. \n References to objects + with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate + Conditions set on the containing object." + properties: + group: + default: "" + description: Group is the group of the referent. For + example, "networking.k8s.io". When unspecified (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: Secret + 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 + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. + \n Note that when a namespace is specified, a ReferencePolicy + object is required in the referent namespace to + allow that namespace's owner to accept the reference. + See the ReferencePolicy documentation for details. + \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + maxItems: 64 + type: array mode: default: Terminate description: "Mode defines the TLS behavior for the TLS session initiated by the client. There are two possible - modes: - Terminate: The TLS session between the downstream + modes: \n - Terminate: The TLS session between the downstream client and the Gateway is terminated at the Gateway. - This mode requires certificateRef to be set. - Passthrough: - The TLS session is NOT terminated by the Gateway. This - \ implies that the Gateway can't decipher the TLS stream - except for the ClientHello message of the TLS protocol. - \ CertificateRef field is ignored in this mode. \n Support: - Core" + This mode requires certificateRefs to be set and contain + at least one element. - Passthrough: The TLS session is + NOT terminated by the Gateway. This implies that the + Gateway can't decipher the TLS stream except for the + ClientHello message of the TLS protocol. CertificateRefs + field is ignored in this mode. \n Support: Core" enum: - Terminate - Passthrough type: string options: additionalProperties: + description: AnnotationValue is the value of an annotation + in Gateway API. This is used for validation of maps + such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation + in that case is based on the entire size of the annotations + struct. + maxLength: 4096 + minLength: 0 type: string - description: "Options are a list of key/value pairs to give - extended options to the provider. \n There variation among - providers as to how ciphersuites are expressed. If there - is a common subset for expressing ciphers then it will - make sense to loft that as a core API construct. \n Support: - Implementation-specific" - type: object - routeOverride: - default: - certificate: Deny - description: "RouteOverride dictates if TLS settings can - be configured via Routes or not. \n CertificateRef must - be defined even if `routeOverride.certificate` is set - to 'Allow' as it will be used as the default certificate - for the listener. \n Support: Core" - properties: - certificate: - default: Deny - description: "Certificate dictates if TLS certificates - can be configured via Routes. If set to 'Allow', a - TLS certificate for a hostname defined in a Route - takes precedence over the certificate defined in Gateway. - \n Support: Core" - enum: - - Allow - - Deny - type: string + description: "Options are a list of key/value pairs to enable + extended TLS configuration for each implementation. For + example, configuring the minimum TLS version or supported + cipher suites. \n A set of common keys MAY be defined + by the API in the future. To avoid any ambiguity, implementation-specific + definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. + Un-prefixed names are reserved for key names defined by + Gateway API. \n Support: Implementation-specific" + maxProperties: 16 type: object type: object required: + - name - port - protocol - - routes type: object maxItems: 64 minItems: 1 type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map required: - gatewayClassName - listeners @@ -446,24 +446,25 @@ spec: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: NotReconciled - status: "False" + status: Unknown type: Scheduled description: Status defines the current state of Gateway. properties: addresses: - description: "Addresses lists the IP addresses that have actually - been bound to the Gateway. These addresses may differ from the addresses + description: Addresses lists the IP addresses that have actually been + bound to the Gateway. These addresses may differ from the addresses in the Spec, e.g. if the Gateway automatically assigns an address - from a reserved pool. \n These addresses should all be of type \"IPAddress\"." + from a reserved pool. items: description: GatewayAddress describes an address that can be bound to a Gateway. properties: type: default: IPAddress - description: "Type of the address. \n Support: Extended" + description: Type of the address. enum: - IPAddress + - Hostname - NamedAddress type: string value: @@ -483,7 +484,7 @@ spec: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: NotReconciled - status: "False" + status: Unknown type: Scheduled description: "Conditions describe the current conditions of the Gateway. \n Implementations should prefer to express Gateway conditions using @@ -569,6 +570,11 @@ spec: items: description: ListenerStatus is the status associated with a Listener. properties: + attachedRoutes: + description: AttachedRoutes represents the total number of Routes + that have been successfully attached to this Listener. + format: int32 + type: integer conditions: description: Conditions describe the current condition of this listener. @@ -648,34 +654,58 @@ spec: x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map - hostname: - description: Hostname is the Listener hostname value for which - this message is reporting the status. + name: + description: Name is the name of the Listener that this status + corresponds to. 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 - port: - description: Port is the unique Listener port value for which - this message is reporting the status. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - protocol: - description: Protocol is the Listener protocol value for which - this message is reporting the status. - type: string + supportedKinds: + description: "SupportedKinds is the list indicating the Kinds + supported by this listener. This MUST represent the kinds + an implementation supports for that Listener configuration. + \n If kinds are specified in Spec that are not supported, + they MUST NOT appear in this list and an implementation MUST + set the \"ResolvedRefs\" condition to \"False\" with the \"InvalidRouteKinds\" + reason. If both valid and invalid Route kinds are specified, + the implementation MUST reference the valid Route kinds that + have been specified." + items: + description: RouteGroupKind indicates the group and kind of + a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + 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 the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array required: + - attachedRoutes - conditions - - port - - protocol + - name + - supportedKinds type: object maxItems: 64 type: array x-kubernetes-list-map-keys: - - port + - name x-kubernetes-list-type: map type: object + required: + - spec type: object served: true storage: true diff --git a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_httproutes.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_httproutes.yaml new file mode 100644 index 000000000..fc574151a --- /dev/null +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_httproutes.yaml @@ -0,0 +1,1284 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + creationTimestamp: null + name: httproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: HTTPRoute + listKind: HTTPRouteList + plural: httproutes + singular: httproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: HTTPRoute provides a way to route HTTP requests. This includes + the capability to match requests by hostname, path, header, or query param. + Filters can be used to specify additional processing steps. Backends specify + where matching requests should be routed. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of HTTPRoute. + properties: + hostnames: + description: "Hostnames defines a set of hostname that should match + against the HTTP Host header to select a HTTPRoute to process the + request. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may + be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n If a hostname is specified + by both the Listener and HTTPRoute, there must be at least one intersecting + hostname for the HTTPRoute to be attached to the Listener. For example: + \n * A Listener with `test.example.com` as the hostname matches + HTTPRoutes that have either not specified any hostnames, or have + specified at least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches HTTPRoutes + \ that have either not specified any hostnames or have specified + at least one hostname that matches the Listener hostname. For + example, `test.example.com` and `*.example.com` would both match. + On the other hand, `example.com` and `test.example.net` would + not match. \n If both the Listener and HTTPRoute have specified + hostnames, any HTTPRoute hostnames that do not match the Listener + hostname MUST be ignored. For example, if a Listener specified `*.example.com`, + and the HTTPRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. \n If both + the Listener and HTTPRoute have specified hostnames, and none match + with the criteria above, then the HTTPRoute is not accepted. The + implementation must raise an 'Accepted' Condition with a status + of `False` in the corresponding RouteParentStatus. \n Support: Core" + items: + description: "Hostname is the fully qualified domain name of a network + host. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname + may be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n Hostname can be \"precise\" + which is a domain name without the terminating dot of a network + host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain + name prefixed with a single wildcard label (e.g. `*.example.com`). + \n Note that as per RFC1035 and RFC1123, a *label* must consist + of lower case alphanumeric characters or '-', and must start and + end with an alphanumeric character. No other punctuation is allowed." + 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 + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) + that a Route wants to be attached to. Note that the referenced parent + resource needs to allow this for the attachment to be complete. + For Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. \n The only kind of parent resource + with \"Core\" support is Gateway. This API may be extended in the + future to support additional kinds of parent resources such as one + of the route kinds. \n It is invalid to reference an identical parent + more than once. It is valid to reference multiple distinct sections + within the same parent resource, such as 2 Listeners within a Gateway. + \n It is possible to separately reference multiple distinct objects + that may be collapsed by an implementation. For example, some implementations + may choose to merge compatible Gateway Listeners together. If that + is the case, the list of routes attached to those resources should + also be merged." + items: + description: "ParentRef identifies an API object (usually a Gateway) + that can be considered a parent of this resource (usually a route). + The only kind of parent resource with \"Core\" support is Gateway. + This API may be extended in the future to support additional kinds + of parent resources, such as HTTPRoute. \n The API object must + be valid in the cluster; the Group and Kind must be registered + in the cluster for this reference to be valid. \n References to + objects with invalid Group and Kind are not valid, and must be + rejected by the implementation, with appropriate Conditions set + on the containing object." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + 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: Gateway + description: "Kind is kind of the referent. \n Support: Core + (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified (or empty string), this refers to the local namespace + of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name + \n Implementations MAY choose to support attaching Routes + to other resources. If that is the case, they MUST clearly + document how SectionName is interpreted. \n When unspecified + (empty string), this will reference the entire resource. For + the purpose of status, an attachment is considered successful + if at least one section in the parent resource accepts it. + For example, Gateway listeners can restrict which Routes can + attach to them by Route kind, namespace, or hostname. If 1 + of 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. \n + 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 + required: + - name + type: object + maxItems: 32 + type: array + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + description: Rules are a list of HTTP matchers, filters and actions. + items: + description: HTTPRouteRule defines semantics for matching an HTTP + request based on conditions (matches), processing it (filters), + and forwarding the request to an API object (backendRefs). + properties: + backendRefs: + description: "If unspecified or invalid (refers to a non-existent + resource or a Service with no endpoints), the rule performs + no forwarding. If there are also no filters specified that + would result in a response being sent, a HTTP 503 status code + is returned. 503 responses must be sent so that the overall + weight is respected; if an invalid backend is requested to + have 80% of requests, then 80% of requests must get a 503 + instead. \n Support: Core for Kubernetes Service Support: + Custom for any other resource \n Support for weight: Core" + items: + description: HTTPBackendRef defines how a HTTPRoute should + forward an HTTP request. + properties: + filters: + description: "Filters defined at this level should be + executed if and only if the request is being forwarded + to the backend defined here. \n Support: Custom (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. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. + For example, "networking.k8s.io". When unspecified + (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 + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema + for a filter that modifies request headers. \n + 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. \n Input: GET /foo + HTTP/1.1 my-header: foo \n Config: add: + \ - name: \"my-header\" value: \"bar\" + \n Output: GET /foo HTTP/1.1 my-header: + foo 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). + \n 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 + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - 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). + \n Input: GET /foo HTTP/1.1 my-header1: + foo my-header2: bar my-header3: baz \n + Config: remove: [\"my-header1\", \"my-header3\"] + \n Output: GET /foo HTTP/1.1 my-header2: + bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with + the given header (name, value) before the + action. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: set: - name: \"my-header\" + \ value: \"bar\" \n 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). + \n 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 + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + 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. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource + where mirrored requests are sent. \n 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. \n If there is + a cross-namespace reference to an *existing* + object that is not allowed by a ReferencePolicy, + 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. \n In either error case, the + Message of the `ResolvedRefs` Condition should + be used to provide more detail about the problem. + \n Support: Extended for Kubernetes Service + Support: Custom for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "networking.k8s.io". When + unspecified (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 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 + namespace: + description: "Namespace is the namespace + of the backend. When unspecified, the + local namespace is inferred. \n Note that + when a namespace is specified, a ReferencePolicy + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferencePolicy + documentation for details. \n 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. For other resources, + destination port might be derived from + the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for + a filter that responds to the request with an + HTTP redirection. \n 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 + of the request is used. \n 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 + port: + description: "Port is the port to be used in + the value of the `Location` header in the + response. When empty, port (if specified) + of the request is used. \n 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. \n Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status + code to be used in response. \n Support: Core" + enum: + - 301 + - 302 + type: integer + type: object + type: + description: "Type identifies the type of filter + to apply. As with other API fields, types are + classified into three conformance levels: \n - + Core: Filter types and their corresponding configuration + defined by \"Support: Core\" in this package, + e.g. \"RequestHeaderModifier\". All implementations + must support core filters. \n - Extended: Filter + types and their corresponding configuration defined + by \"Support: Extended\" in this package, e.g. + \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Custom: 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. \n Implementers are encouraged + to define custom implementation types to extend + the core API with implementation-specific behavior. + \n 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." + enum: + - RequestHeaderModifier + - RequestMirror + - RequestRedirect + - ExtensionRef + type: string + required: + - type + type: object + maxItems: 16 + type: array + group: + default: "" + description: Group is the group of the referent. For example, + "networking.k8s.io". When unspecified (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 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 + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace is specified, a ReferencePolicy + object is required in the referent namespace to allow + that namespace's owner to accept the reference. See + the ReferencePolicy documentation for details. \n 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. For other resources, + destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests + forwarded to the referenced backend. This is computed + as weight/(sum of all weights in this BackendRefs list). + For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision + an implementation supports. Weight is not a percentage + and the sum of weights does not need to equal 100. \n + If only one backend is specified and it has a weight + greater than 0, 100% of the traffic is forwarded to + that backend. If weight is set to 0, no traffic should + be forwarded for this entry. If unspecified, weight + defaults to 1. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + maxItems: 16 + type: array + filters: + description: "Filters define the filters that are applied to + requests that match this rule. \n The effects of ordering + of multiple behaviors are currently unspecified. This can + change in the future based on feedback during the alpha stage. + \n Conformance-levels at this level are defined based on the + type of filter: \n - ALL core filters MUST be supported by + all implementations. - Implementers are encouraged to support + extended filters. - Implementation-specific custom filters + have no API guarantees across implementations. \n Specifying + a core filter multiple times has unspecified or custom conformance. + \n Support: Core" + 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. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. For + example, "networking.k8s.io". When unspecified (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 + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for + a filter that modifies request headers. \n 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. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: add: - name: \"my-header\" value: + \"bar\" \n Output: GET /foo HTTP/1.1 my-header: + foo 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). + \n 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 + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - 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). + \n Input: GET /foo HTTP/1.1 my-header1: foo + \ my-header2: bar my-header3: baz \n Config: + \ remove: [\"my-header1\", \"my-header3\"] \n Output: + \ GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with the + given header (name, value) before the action. \n + Input: GET /foo HTTP/1.1 my-header: foo \n Config: + \ set: - name: \"my-header\" value: \"bar\" + \n 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). + \n 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 + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + 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. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where + mirrored requests are sent. \n 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. \n If + there is a cross-namespace reference to an *existing* + object that is not allowed by a ReferencePolicy, + 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. \n + In either error case, the Message of the `ResolvedRefs` + Condition should be used to provide more detail + about the problem. \n Support: Extended for Kubernetes + Service Support: Custom for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "networking.k8s.io". When unspecified + (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 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 + namespace: + description: "Namespace is the namespace of the + backend. When unspecified, the local namespace + is inferred. \n Note that when a namespace is + specified, a ReferencePolicy object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferencePolicy + documentation for details. \n 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. For + other resources, destination port might be derived + from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for a filter + that responds to the request with an HTTP redirection. + \n 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 of the request is used. + \n 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 + port: + description: "Port is the port to be used in the value + of the `Location` header in the response. When empty, + port (if specified) of the request is used. \n 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. \n + Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status code to + be used in response. \n Support: Core" + enum: + - 301 + - 302 + type: integer + type: object + type: + description: "Type identifies the type of filter to apply. + As with other API fields, types are classified into + three conformance levels: \n - Core: Filter types and + their corresponding configuration defined by \"Support: + Core\" in this package, e.g. \"RequestHeaderModifier\". + All implementations must support core filters. \n + - Extended: Filter types and their corresponding configuration + defined by \"Support: Extended\" in this package, + e.g. \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Custom: 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. \n + Implementers are encouraged to define custom implementation + types to extend the core API with implementation-specific + behavior. \n 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." + enum: + - RequestHeaderModifier + - RequestMirror + - RequestRedirect + - ExtensionRef + type: string + required: + - type + type: object + maxItems: 16 + type: array + matches: + default: + - path: + type: PathPrefix + value: / + description: "Matches define conditions used for matching the + rule against incoming HTTP requests. Each match is independent, + i.e. this rule will be matched if **any** one of the matches + is satisfied. \n For example, take the following matches configuration: + \n ``` matches: - path: value: \"/foo\" headers: - + name: \"version\" value: \"v2\" - path: value: \"/v2/foo\" + ``` \n For a request to match against this rule, a request + must satisfy EITHER of the two conditions: \n - path prefixed + with `/foo` AND contains the header `version: v2` - path prefix + of `/v2/foo` \n See the documentation for HTTPRouteMatch on + how to specify multiple match conditions that should be ANDed + together. \n If no matches are specified, the default is a + prefix path match on \"/\", which has the effect of matching + every HTTP request. \n Proxy or Load Balancer routing configuration + generated from HTTPRoutes MUST prioritize rules based on the + following criteria, continuing on ties. Precedence must be + given to the the Rule with the largest number of: \n * Characters + in a matching non-wildcard hostname. * Characters in a matching + hostname. * Characters in a matching path. * Header matches. + * Query param matches. \n If ties still exist across multiple + Routes, matching precedence MUST be determined in order of + the following criteria, continuing on ties: \n * The oldest + Route based on creation timestamp. * The Route appearing first + in alphabetical order by \"/\". \n If ties + still exist within the Route that has been given precedence, + matching precedence MUST be granted to the first matching + rule meeting the above criteria." + items: + description: "HTTPRouteMatch defines the predicate used to + match requests to a given action. Multiple match types are + ANDed together, i.e. the match will evaluate to true only + if all conditions are satisfied. \n For example, the match + below will match a HTTP request only if its path starts + with `/foo` AND it contains the `version: v1` header: \n + ``` match: path: value: \"/foo\" headers: - name: + \"version\" value \"v1\" ```" + properties: + headers: + description: Headers specifies HTTP request header matchers. + Multiple match values are ANDed together, meaning, a + request must match all the specified headers to select + the route. + items: + description: HTTPHeaderMatch describes how to select + a HTTP route by matching HTTP request headers. + 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). + \n If multiple entries specify equivalent header + names, only 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. + \n When a header is repeated in an HTTP request, + it is implementation-specific behavior as to how + this is represented. Generally, proxies should + follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 + regarding processing a repeated header, with special + handling for \"Set-Cookie\"." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: "Type specifies how to match against + the value of the header. \n Support: Core (Exact) + \n Support: Custom (RegularExpression) \n Since + RegularExpression HeaderMatchType has custom conformance, + implementations can support POSIX, PCRE or any + other dialects of regular expressions. Please + read the implementation's documentation to determine + the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to + be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: "Method specifies HTTP method matcher. When + specified, this route will be matched only if the request + has the specified method. \n Support: Extended" + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + description: Path specifies a HTTP request path matcher. + If this field is not specified, a default prefix match + on the "/" path is provided. + properties: + type: + default: PathPrefix + description: "Type specifies how to match against + the path Value. \n Support: Core (Exact, PathPrefix) + \n Support: Custom (RegularExpression)" + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + queryParams: + description: QueryParams specifies HTTP query parameter + matchers. Multiple match values are ANDed together, + meaning, a request must match all the specified query + parameters to select the route. + items: + description: HTTPQueryParamMatch describes how to select + a HTTP route by matching HTTP query parameters. + properties: + name: + description: Name is the name of the HTTP query + param to be matched. This must be an exact string + match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). + maxLength: 256 + minLength: 1 + type: string + type: + default: Exact + description: "Type specifies how to match against + the value of the query parameter. \n Support: + Extended (Exact) \n Support: Custom (RegularExpression) + \n Since RegularExpression QueryParamMatchType + has custom conformance, implementations can support + POSIX, PCRE or any other dialects of regular expressions. + Please read the implementation's documentation + to determine the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param + to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + type: object + maxItems: 16 + type: array + type: object + status: + description: Status defines the current state of HTTPRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) + that are associated with the route, and the status of the route + with respect to each parent. When this route attaches to a parent, + the controller that manages the parent must add an entry to this + list when the controller first sees the route and should update + the entry as appropriate when the route or gateway is modified. + \n Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this + API can only populate Route status for the Gateways/parent resources + they are responsible for. \n A maximum of 32 Gateways will be represented + in this list. An empty list means the route has not been attached + to any Gateway." + items: + description: RouteParentStatus describes the status of a route with + respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with + respect to the Gateway. Note that the route's availability + is also subject to the Gateway's own status conditions and + listener status. \n If the Route's ParentRef specifies an + existing Gateway that supports Routes of this kind AND that + Gateway's controller has sufficient access, then that Gateway's + controller MUST set the \"Accepted\" condition on the Route, + to indicate whether the route has been accepted or rejected + by the Gateway, and why. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec + that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + 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: Gateway + description: "Kind is kind of the referent. \n Support: + Core (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified (or empty string), this refers to the + local namespace of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name \n Implementations MAY choose to support attaching + Routes to other resources. If that is the case, they MUST + clearly document how SectionName is interpreted. \n When + unspecified (empty string), this will reference the entire + resource. For the purpose of status, an attachment is + considered successful if at least one section in the parent + resource accepts it. For example, Gateway listeners can + restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept + attachment from the referencing Route, the Route MUST + be considered successfully attached. If no Gateway listeners + accept attachment from this Route, the Route MUST be considered + detached from the Gateway. \n 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 + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tcproutes.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tcproutes.yaml new file mode 100644 index 000000000..b7bf7ff16 --- /dev/null +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tcproutes.yaml @@ -0,0 +1,431 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + creationTimestamp: null + name: tcproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: TCPRoute + listKind: TCPRouteList + plural: tcproutes + singular: tcproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: TCPRoute provides a way to route TCP requests. When combined + with a Gateway listener, it can be used to forward connections on the port + specified by the listener to a set of backends specified by the TCPRoute. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of TCPRoute. + properties: + parentRefs: + description: "ParentRefs references the resources (usually Gateways) + that a Route wants to be attached to. Note that the referenced parent + resource needs to allow this for the attachment to be complete. + For Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. \n The only kind of parent resource + with \"Core\" support is Gateway. This API may be extended in the + future to support additional kinds of parent resources such as one + of the route kinds. \n It is invalid to reference an identical parent + more than once. It is valid to reference multiple distinct sections + within the same parent resource, such as 2 Listeners within a Gateway. + \n It is possible to separately reference multiple distinct objects + that may be collapsed by an implementation. For example, some implementations + may choose to merge compatible Gateway Listeners together. If that + is the case, the list of routes attached to those resources should + also be merged." + items: + description: "ParentRef identifies an API object (usually a Gateway) + that can be considered a parent of this resource (usually a route). + The only kind of parent resource with \"Core\" support is Gateway. + This API may be extended in the future to support additional kinds + of parent resources, such as HTTPRoute. \n The API object must + be valid in the cluster; the Group and Kind must be registered + in the cluster for this reference to be valid. \n References to + objects with invalid Group and Kind are not valid, and must be + rejected by the implementation, with appropriate Conditions set + on the containing object." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + 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: Gateway + description: "Kind is kind of the referent. \n Support: Core + (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified (or empty string), this refers to the local namespace + of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name + \n Implementations MAY choose to support attaching Routes + to other resources. If that is the case, they MUST clearly + document how SectionName is interpreted. \n When unspecified + (empty string), this will reference the entire resource. For + the purpose of status, an attachment is considered successful + if at least one section in the parent resource accepts it. + For example, Gateway listeners can restrict which Routes can + attach to them by Route kind, namespace, or hostname. If 1 + of 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. \n + 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 + required: + - name + type: object + maxItems: 32 + type: array + rules: + description: Rules are a list of TCP matchers and actions. + items: + description: TCPRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching + requests should be sent. If unspecified or invalid (refers + to a non-existent resource or a Service with no endpoints), + the underlying implementation MUST actively reject connection + attempts to this backend. Connection rejections must respect + weight; if an invalid backend is requested to have 80% of + connections, then 80% of connections must be rejected instead. + \n Support: Core for Kubernetes Service Support: Custom for + any other resource \n Support for weight: Extended" + items: + description: "BackendRef defines how a Route should forward + a request to a Kubernetes resource. \n Note that when a + namespace is specified, a ReferencePolicy object is required + in the referent namespace to allow that namespace's owner + to accept the reference. See the ReferencePolicy documentation + for details." + properties: + group: + default: "" + description: Group is the group of the referent. For example, + "networking.k8s.io". When unspecified (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 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 + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace is specified, a ReferencePolicy + object is required in the referent namespace to allow + that namespace's owner to accept the reference. See + the ReferencePolicy documentation for details. \n 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. For other resources, + destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests + forwarded to the referenced backend. This is computed + as weight/(sum of all weights in this BackendRefs list). + For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision + an implementation supports. Weight is not a percentage + and the sum of weights does not need to equal 100. \n + If only one backend is specified and it has a weight + greater than 0, 100% of the traffic is forwarded to + that backend. If weight is set to 0, no traffic should + be forwarded for this entry. If unspecified, weight + defaults to 1. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + maxItems: 16 + minItems: 1 + type: array + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - rules + type: object + status: + description: Status defines the current state of TCPRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) + that are associated with the route, and the status of the route + with respect to each parent. When this route attaches to a parent, + the controller that manages the parent must add an entry to this + list when the controller first sees the route and should update + the entry as appropriate when the route or gateway is modified. + \n Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this + API can only populate Route status for the Gateways/parent resources + they are responsible for. \n A maximum of 32 Gateways will be represented + in this list. An empty list means the route has not been attached + to any Gateway." + items: + description: RouteParentStatus describes the status of a route with + respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with + respect to the Gateway. Note that the route's availability + is also subject to the Gateway's own status conditions and + listener status. \n If the Route's ParentRef specifies an + existing Gateway that supports Routes of this kind AND that + Gateway's controller has sufficient access, then that Gateway's + controller MUST set the \"Accepted\" condition on the Route, + to indicate whether the route has been accepted or rejected + by the Gateway, and why. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec + that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + 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: Gateway + description: "Kind is kind of the referent. \n Support: + Core (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified (or empty string), this refers to the + local namespace of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name \n Implementations MAY choose to support attaching + Routes to other resources. If that is the case, they MUST + clearly document how SectionName is interpreted. \n When + unspecified (empty string), this will reference the entire + resource. For the purpose of status, an attachment is + considered successful if at least one section in the parent + resource accepts it. For example, Gateway listeners can + restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept + attachment from the referencing Route, the Route MUST + be considered successfully attached. If no Gateway listeners + accept attachment from this Route, the Route MUST be considered + detached from the Gateway. \n 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 + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tlsroutes.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tlsroutes.yaml new file mode 100644 index 000000000..ab3b49990 --- /dev/null +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tlsroutes.yaml @@ -0,0 +1,480 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + creationTimestamp: null + name: tlsroutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: TLSRoute + listKind: TLSRouteList + plural: tlsroutes + singular: tlsroute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: "The TLSRoute resource is similar to TCPRoute, but can be configured + to match against TLS-specific metadata. This allows more flexibility in + matching streams for a given TLS listener. \n If you need to forward traffic + to a single target for a TLS listener, you could choose to use a TCPRoute + with a TLS listener." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of TLSRoute. + properties: + hostnames: + description: "Hostnames defines a set of SNI names that should match + against the SNI attribute of TLS ClientHello message in TLS handshake. + This matches the RFC 1123 definition of a hostname with 2 notable + exceptions: \n 1. IPs are not allowed in SNI names per RFC 6066. + 2. A hostname may be prefixed with a wildcard label (`*.`). The + wildcard label must appear by itself as the first label. \n If + a hostname is specified by both the Listener and TLSRoute, there + must be at least one intersecting hostname for the TLSRoute to be + attached to the Listener. For example: \n * A Listener with `test.example.com` + as the hostname matches TLSRoutes that have either not specified + any hostnames, or have specified at least one of `test.example.com` + or `*.example.com`. * A Listener with `*.example.com` as the hostname + matches TLSRoutes that have either not specified any hostnames + or have specified at least one hostname that matches the Listener + hostname. For example, `test.example.com` and `*.example.com` + would both match. On the other hand, `example.com` and `test.example.net` + would not match. \n If both the Listener and TLSRoute have specified + hostnames, any TLSRoute hostnames that do not match the Listener + hostname MUST be ignored. For example, if a Listener specified `*.example.com`, + and the TLSRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. \n If both + the Listener and TLSRoute have specified hostnames, and none match + with the criteria above, then the TLSRoute is not accepted. The + implementation must raise an 'Accepted' Condition with a status + of `False` in the corresponding RouteParentStatus. \n Support: Core" + items: + description: "Hostname is the fully qualified domain name of a network + host. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname + may be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n Hostname can be \"precise\" + which is a domain name without the terminating dot of a network + host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain + name prefixed with a single wildcard label (e.g. `*.example.com`). + \n Note that as per RFC1035 and RFC1123, a *label* must consist + of lower case alphanumeric characters or '-', and must start and + end with an alphanumeric character. No other punctuation is allowed." + 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 + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) + that a Route wants to be attached to. Note that the referenced parent + resource needs to allow this for the attachment to be complete. + For Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. \n The only kind of parent resource + with \"Core\" support is Gateway. This API may be extended in the + future to support additional kinds of parent resources such as one + of the route kinds. \n It is invalid to reference an identical parent + more than once. It is valid to reference multiple distinct sections + within the same parent resource, such as 2 Listeners within a Gateway. + \n It is possible to separately reference multiple distinct objects + that may be collapsed by an implementation. For example, some implementations + may choose to merge compatible Gateway Listeners together. If that + is the case, the list of routes attached to those resources should + also be merged." + items: + description: "ParentRef identifies an API object (usually a Gateway) + that can be considered a parent of this resource (usually a route). + The only kind of parent resource with \"Core\" support is Gateway. + This API may be extended in the future to support additional kinds + of parent resources, such as HTTPRoute. \n The API object must + be valid in the cluster; the Group and Kind must be registered + in the cluster for this reference to be valid. \n References to + objects with invalid Group and Kind are not valid, and must be + rejected by the implementation, with appropriate Conditions set + on the containing object." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + 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: Gateway + description: "Kind is kind of the referent. \n Support: Core + (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified (or empty string), this refers to the local namespace + of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name + \n Implementations MAY choose to support attaching Routes + to other resources. If that is the case, they MUST clearly + document how SectionName is interpreted. \n When unspecified + (empty string), this will reference the entire resource. For + the purpose of status, an attachment is considered successful + if at least one section in the parent resource accepts it. + For example, Gateway listeners can restrict which Routes can + attach to them by Route kind, namespace, or hostname. If 1 + of 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. \n + 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 + required: + - name + type: object + maxItems: 32 + type: array + rules: + description: Rules are a list of TLS matchers and actions. + items: + description: TLSRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching + requests should be sent. If unspecified or invalid (refers + to a non-existent resource or a Service with no endpoints), + the rule performs no forwarding; if no filters are specified + that would result in a response being sent, the underlying + implementation must actively reject request attempts to this + backend, by rejecting the connection or returning a 503 status + code. Request rejections must respect weight; if an invalid + backend is requested to have 80% of requests, then 80% of + requests must be rejected instead. \n Support: Core for Kubernetes + Service Support: Custom for any other resource \n Support + for weight: Extended" + items: + description: "BackendRef defines how a Route should forward + a request to a Kubernetes resource. \n Note that when a + namespace is specified, a ReferencePolicy object is required + in the referent namespace to allow that namespace's owner + to accept the reference. See the ReferencePolicy documentation + for details." + properties: + group: + default: "" + description: Group is the group of the referent. For example, + "networking.k8s.io". When unspecified (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 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 + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace is specified, a ReferencePolicy + object is required in the referent namespace to allow + that namespace's owner to accept the reference. See + the ReferencePolicy documentation for details. \n 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. For other resources, + destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests + forwarded to the referenced backend. This is computed + as weight/(sum of all weights in this BackendRefs list). + For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision + an implementation supports. Weight is not a percentage + and the sum of weights does not need to equal 100. \n + If only one backend is specified and it has a weight + greater than 0, 100% of the traffic is forwarded to + that backend. If weight is set to 0, no traffic should + be forwarded for this entry. If unspecified, weight + defaults to 1. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + maxItems: 16 + minItems: 1 + type: array + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - rules + type: object + status: + description: Status defines the current state of TLSRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) + that are associated with the route, and the status of the route + with respect to each parent. When this route attaches to a parent, + the controller that manages the parent must add an entry to this + list when the controller first sees the route and should update + the entry as appropriate when the route or gateway is modified. + \n Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this + API can only populate Route status for the Gateways/parent resources + they are responsible for. \n A maximum of 32 Gateways will be represented + in this list. An empty list means the route has not been attached + to any Gateway." + items: + description: RouteParentStatus describes the status of a route with + respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with + respect to the Gateway. Note that the route's availability + is also subject to the Gateway's own status conditions and + listener status. \n If the Route's ParentRef specifies an + existing Gateway that supports Routes of this kind AND that + Gateway's controller has sufficient access, then that Gateway's + controller MUST set the \"Accepted\" condition on the Route, + to indicate whether the route has been accepted or rejected + by the Gateway, and why. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec + that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + 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: Gateway + description: "Kind is kind of the referent. \n Support: + Core (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified (or empty string), this refers to the + local namespace of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name \n Implementations MAY choose to support attaching + Routes to other resources. If that is the case, they MUST + clearly document how SectionName is interpreted. \n When + unspecified (empty string), this will reference the entire + resource. For the purpose of status, an attachment is + considered successful if at least one section in the parent + resource accepts it. For example, Gateway listeners can + restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept + attachment from the referencing Route, the Route MUST + be considered successfully attached. If no Gateway listeners + accept attachment from this Route, the Route MUST be considered + detached from the Gateway. \n 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 + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/docs/content/reference/dynamic-configuration/kubernetes-gateway-rbac.yml b/docs/content/reference/dynamic-configuration/kubernetes-gateway-rbac.yml index 7d04a81cf..36daee506 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-gateway-rbac.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-gateway-rbac.yml @@ -22,7 +22,7 @@ rules: - list - watch - apiGroups: - - networking.x-k8s.io + - gateway.networking.k8s.io resources: - gatewayclasses - gateways @@ -34,7 +34,7 @@ rules: - list - watch - apiGroups: - - networking.x-k8s.io + - gateway.networking.k8s.io resources: - gatewayclasses/status - gateways/status @@ -49,7 +49,6 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-controller - roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/docs/content/reference/dynamic-configuration/kubernetes-gateway-resource.yml b/docs/content/reference/dynamic-configuration/kubernetes-gateway-resource.yml index 5abd2f344..74ebef030 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-gateway-resource.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-gateway-resource.yml @@ -1,124 +1,116 @@ --- +apiVersion: gateway.networking.k8s.io/v1alpha2 kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- +apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute - namespaces: - from: Same - selector: - matchLabels: - app: foo - - protocol: HTTPS - port: 443 - tls: - certificateRef: - group: "core" - kind: "Secret" - name: "mysecret" - routes: - kind: HTTPRoute - selector: - matchLabels: - app: foo - - protocol: TCP + + - name: https + protocol: HTTPS + port: 443 + tls: + certificateRefs: + - kind: Secret + name: mysecret + + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute - namespaces: - from: Same - selector: - matchLabels: - app: footcp - - protocol: TLS + allowedRoutes: + kinds: + - kind: TCPRoute + + - name: tls + protocol: TLS port: 9443 hostname: example.com tls: - certificateRef: - group: "core" - kind: "Secret" - name: "mysecret" - routes: - kind: TLSRoute - namespaces: - from: Same - selector: - matchLabels: - app: footls + - certificateRefs: + - kind: Secret + name: mysecret --- +apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 metadata: - name: http-app-1 + name: http-app namespace: default - labels: - app: foo + spec: + parentRefs: + - name: my-gateway + hostnames: - - "foo.com" + - foo.com + rules: - matches: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + + backendRefs: + - name: whoami port: 80 weight: 1 + - matches: - path: - type: Prefix + type: PathPrefix value: /foo - forwardTo: - - backendRef: - group: traefik.containo.us - kind: TraefikService - name: myservice@file + + backendRefs: + - group: traefik.containo.us + kind: TraefikService + name: myservice@file weight: 1 port: 80 --- +apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 metadata: - name: tcp-app-1 + name: tcp-app namespace: default - labels: - app: footcp + spec: + parentRefs: + - name: my-gateway + rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 --- +apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 metadata: - name: tls-app-1 + name: tls-app namespace: default - labels: - app: footls + spec: + parentRefs: + - name: my-gateway + sectionName: tls + rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 diff --git a/docs/content/reference/dynamic-configuration/kubernetes-gateway-simple-https.yml b/docs/content/reference/dynamic-configuration/kubernetes-gateway-simple-https.yml index 24e4efff8..c16a5dc2f 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-gateway-simple-https.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-gateway-simple-https.yml @@ -1,48 +1,50 @@ --- +apiVersion: gateway.networking.k8s.io/v1alpha2 kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 metadata: name: my-gateway-class + spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- +apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 metadata: name: my-gateway + spec: gatewayClassName: my-gateway-class listeners: - - protocol: HTTPS + - name: https + protocol: HTTPS port: 443 tls: - certificateRef: - group: "core" - kind: "Secret" - name: "mysecret" - routes: - kind: HTTPRoute - selector: - matchLabels: - app: foo + certificateRefs: + - kind: Secret + name: mysecret + --- +apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 metadata: - name: http-app-1 + name: http-app namespace: default - labels: - app: foo + spec: + parentRefs: + - name: my-gateway + hostnames: - - "whoami" + - whoami + rules: - matches: - path: type: Exact value: /foo - forwardTo: - - serviceName: whoami + + backendRefs: + - name: whoami port: 80 weight: 1 diff --git a/docs/content/reference/dynamic-configuration/kubernetes-gateway-traefik-lb-svc.yml b/docs/content/reference/dynamic-configuration/kubernetes-gateway-traefik-lb-svc.yml index 1e90422a4..1ac973829 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-gateway-traefik-lb-svc.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-gateway-traefik-lb-svc.yml @@ -5,8 +5,8 @@ metadata: name: traefik-controller --- -kind: Deployment apiVersion: apps/v1 +kind: Deployment metadata: name: traefik @@ -15,24 +15,27 @@ spec: selector: matchLabels: app: traefik-lb + template: metadata: labels: app: traefik-lb + spec: serviceAccountName: traefik-controller containers: - name: traefik - image: traefik/traefik:latest - imagePullPolicy: IfNotPresent + image: traefik:v2.5 args: - --entrypoints.web.address=:80 - --entrypoints.websecure.address=:443 - --experimental.kubernetesgateway - --providers.kubernetesgateway + ports: - name: web containerPort: 80 + - name: websecure containerPort: 443 @@ -41,16 +44,19 @@ apiVersion: v1 kind: Service metadata: name: traefik + spec: + type: LoadBalancer selector: app: traefik-lb + ports: - protocol: TCP port: 80 targetPort: web name: web + - protocol: TCP port: 443 targetPort: websecure name: websecure - type: LoadBalancer diff --git a/docs/content/reference/dynamic-configuration/kubernetes-gateway.md b/docs/content/reference/dynamic-configuration/kubernetes-gateway.md index e6fddbe24..8b668b445 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-gateway.md +++ b/docs/content/reference/dynamic-configuration/kubernetes-gateway.md @@ -6,11 +6,11 @@ Dynamic configuration with Kubernetes Gateway provider. ## Definitions ```yaml ---8<-- "content/reference/dynamic-configuration/networking.x-k8s.io_gatewayclasses.yaml" ---8<-- "content/reference/dynamic-configuration/networking.x-k8s.io_gateways.yaml" ---8<-- "content/reference/dynamic-configuration/networking.x-k8s.io_httproutes.yaml" ---8<-- "content/reference/dynamic-configuration/networking.x-k8s.io_tcproutes.yaml" ---8<-- "content/reference/dynamic-configuration/networking.x-k8s.io_tlsroutes.yaml" +--8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_gatewayclasses.yaml" +--8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_gateways.yaml" +--8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_httproutes.yaml" +--8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_tcproutes.yaml" +--8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_tlsroutes.yaml" ``` ## Resources diff --git a/docs/content/reference/dynamic-configuration/kubernetes-whoami-svc.yml b/docs/content/reference/dynamic-configuration/kubernetes-whoami-svc.yml index 486e5d195..32471e4c7 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-whoami-svc.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-whoami-svc.yml @@ -1,6 +1,6 @@ --- -kind: Deployment apiVersion: apps/v1 +kind: Deployment metadata: name: whoami @@ -9,10 +9,12 @@ spec: selector: matchLabels: app: whoami + template: metadata: labels: app: whoami + spec: containers: - name: whoami @@ -25,8 +27,9 @@ metadata: name: whoami spec: + selector: + app: whoami + ports: - protocol: TCP port: 80 - selector: - app: whoami diff --git a/docs/content/reference/dynamic-configuration/networking.x-k8s.io_httproutes.yaml b/docs/content/reference/dynamic-configuration/networking.x-k8s.io_httproutes.yaml deleted file mode 100644 index d64108b70..000000000 --- a/docs/content/reference/dynamic-configuration/networking.x-k8s.io_httproutes.yaml +++ /dev/null @@ -1,971 +0,0 @@ - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - name: httproutes.networking.x-k8s.io -spec: - group: networking.x-k8s.io - names: - categories: - - gateway-api - kind: HTTPRoute - listKind: HTTPRouteList - plural: httproutes - singular: httproute - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.hostnames - name: Hostnames - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: HTTPRoute is the Schema for the HTTPRoute resource. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of HTTPRoute. - properties: - gateways: - default: - allow: SameNamespace - description: Gateways defines which Gateways can use this Route. - properties: - allow: - default: SameNamespace - description: 'Allow indicates which Gateways will be allowed to - use this route. Possible values are: * All: Gateways in any - namespace can use this route. * FromList: Only Gateways specified - in GatewayRefs may use this route. * SameNamespace: Only Gateways - in the same namespace may use this route.' - enum: - - All - - FromList - - SameNamespace - type: string - gatewayRefs: - description: GatewayRefs must be specified when Allow is set to - "FromList". In that case, only Gateways referenced in this list - will be allowed to use this route. This field is ignored for - other values of "Allow". - items: - description: GatewayReference identifies a Gateway in a specified - namespace. - properties: - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace is the namespace of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - namespace - type: object - type: array - type: object - hostnames: - description: "Hostnames defines a set of hostname that should match - against the HTTP Host header to select a HTTPRoute to process the - request. Hostname is the fully qualified domain name of a network - host, as defined by RFC 3986. Note the following deviations from - the \"host\" part of the URI as defined in the RFC: \n 1. IPs are - not allowed. 2. The `:` delimiter is not respected because ports - are not allowed. \n Incoming requests are matched against the hostnames - before the HTTPRoute rules. If no hostname is specified, traffic - is routed based on the HTTPRouteRules. \n Hostname can be \"precise\" - which is a domain name without the terminating dot of a network - host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain - name prefixed with a single wildcard label (e.g. `*.example.com`). - The wildcard character `*` must appear by itself as the first DNS - label and matches only a single label. You cannot have a wildcard - label by itself (e.g. Host == `*`). Requests will be matched against - the Host field in the following order: \n 1. If Host is precise, - the request matches this rule if the HTTP Host header is equal - to Host. 2. If Host is a wildcard, then the request matches this - rule if the HTTP Host header is to equal to the suffix (removing - the first label) of the wildcard rule. \n Support: Core" - items: - description: Hostname is used to specify a hostname that should - be matched. - maxLength: 253 - minLength: 1 - type: string - maxItems: 16 - type: array - rules: - default: - - matches: - - path: - type: Prefix - value: / - description: Rules are a list of HTTP matchers, filters and actions. - items: - description: HTTPRouteRule defines semantics for matching an HTTP - request based on conditions, optionally executing additional processing - steps, and forwarding the request to an API object. - properties: - filters: - description: "Filters define the filters that are applied to - requests that match this rule. \n The effects of ordering - of multiple behaviors are currently unspecified. This can - change in the future based on feedback during the alpha stage. - \n Conformance-levels at this level are defined based on the - type of filter: \n - ALL core filters MUST be supported by - all implementations. - Implementers are encouraged to support - extended filters. - Implementation-specific custom filters - have no API guarantees across implementations. \n Specifying - a core filter multiple times has unspecified or custom conformance. - \n Support: Core" - items: - description: 'HTTPRouteFilter defines additional processing - steps that must be completed during the request or response - lifecycle. HTTPRouteFilters are meant as an extension point - to express additional 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. TODO(hbagdi): re-render - CRDs once controller-tools supports union tags: - https://github.com/kubernetes-sigs/controller-tools/pull/298 - - https://github.com/kubernetes-sigs/controller-tools/issues/461' - properties: - extensionRef: - description: "ExtensionRef is an optional, implementation-specific - extension to the \"filter\" behavior. For example, - resource \"myroutefilter\" in group \"networking.acme.io\"). - ExtensionRef MUST NOT be used for core and extended - filters. \n Support: Implementation-specific" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - requestHeaderModifier: - description: "RequestHeaderModifier defines a schema for - a filter that modifies request headers. \n Support: - Core" - properties: - add: - additionalProperties: - type: string - description: "Add adds the given header (name, value) - to the request before the action. It appends to - any existing values associated with the header name. - \n Input: GET /foo HTTP/1.1 my-header: foo \n - Config: add: {\"my-header\": \"bar\"} \n Output: - \ GET /foo HTTP/1.1 my-header: foo my-header: - bar \n Support: Extended" - type: object - remove: - description: "Remove the given header(s) from the - HTTP request before the action. The value of RemoveHeader - is a list of HTTP header names. Note that the header - names are case-insensitive [RFC-2616 4.2]. \n Input: - \ GET /foo HTTP/1.1 my-header1: foo my-header2: - bar my-header3: baz \n Config: remove: [\"my-header1\", - \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: - bar \n Support: Extended" - items: - type: string - maxItems: 16 - type: array - set: - additionalProperties: - type: string - description: "Set overwrites the request with the - given header (name, value) before the action. \n - Input: GET /foo HTTP/1.1 my-header: foo \n Config: - \ set: {\"my-header\": \"bar\"} \n Output: GET - /foo HTTP/1.1 my-header: bar \n Support: Extended" - type: object - type: object - requestMirror: - description: "RequestMirror defines a schema for a filter - that mirrors requests. \n Support: Extended" - properties: - backendRef: - description: "BackendRef is a local object reference - to mirror matched requests to. If both BackendRef - and ServiceName are specified, ServiceName will - be given precedence. \n If the referent cannot be - found, the rule is not included in the route. The - controller should raise the \"ResolvedRefs\" condition - on the Gateway with the \"DegradedRoutes\" reason. - The gateway status for this route should be updated - with a condition that describes the error more specifically. - \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - port: - description: "Port specifies the destination port - number to use for the backend referenced by the - ServiceName or BackendRef field. \n If unspecified, - the destination port in the request is used when - forwarding to a backendRef or serviceName." - format: int32 - maximum: 65535 - minimum: 1 - type: integer - serviceName: - description: "ServiceName refers to the name of the - Service to mirror matched requests to. When specified, - this takes the place of BackendRef. If both BackendRef - and ServiceName are specified, ServiceName will - be given precedence. \n If the referent cannot be - found, the rule is not included in the route. The - controller should raise the \"ResolvedRefs\" condition - on the Gateway with the \"DegradedRoutes\" reason. - The gateway status for this route should be updated - with a condition that describes the error more specifically. - \n Support: Core" - maxLength: 253 - type: string - type: object - type: - description: "Type identifies the type of filter to apply. - As with other API fields, types are classified into - three conformance levels: \n - Core: Filter types and - their corresponding configuration defined by \"Support: - Core\" in this package, e.g. \"RequestHeaderModifier\". - All implementations must support core filters. \n - - Extended: Filter types and their corresponding configuration - defined by \"Support: Extended\" in this package, - e.g. \"RequestMirror\". Implementers are encouraged - to support extended filters. \n - Custom: 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. \n - Implementers are encouraged to define custom implementation - types to extend the core API with implementation-specific - behavior." - enum: - - RequestHeaderModifier - - RequestMirror - - ExtensionRef - type: string - required: - - type - type: object - maxItems: 16 - type: array - forwardTo: - description: ForwardTo defines the backend(s) where matching - requests should be sent. If unspecified, the rule performs - no forwarding. If unspecified and no filters are specified - that would result in a response being sent, a 503 error code - is returned. - items: - description: HTTPRouteForwardTo defines how a HTTPRoute should - forward a request. - properties: - backendRef: - description: "BackendRef is a reference to a backend to - forward matched requests to. If both BackendRef and - ServiceName are specified, ServiceName will be given - precedence. \n If the referent cannot be found, the - route must be dropped from the Gateway. The controller - should raise the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway status - for this route should be updated with a condition that - describes the error more specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - filters: - description: "Filters defined at this-level should be - executed if and only if the request is being forwarded - to the backend defined here. \n Support: Custom (For - broader support of filters, use the Filters field in - HTTPRouteRule.)" - items: - description: 'HTTPRouteFilter defines additional processing - steps that must be completed during the request or - response lifecycle. HTTPRouteFilters are meant as - an extension point to express additional 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. TODO(hbagdi): - re-render CRDs once controller-tools supports union - tags: - https://github.com/kubernetes-sigs/controller-tools/pull/298 - - https://github.com/kubernetes-sigs/controller-tools/issues/461' - properties: - extensionRef: - description: "ExtensionRef is an optional, implementation-specific - extension to the \"filter\" behavior. For example, - resource \"myroutefilter\" in group \"networking.acme.io\"). - ExtensionRef MUST NOT be used for core and extended - filters. \n Support: Implementation-specific" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - requestHeaderModifier: - description: "RequestHeaderModifier defines a schema - for a filter that modifies request headers. \n - Support: Core" - properties: - add: - additionalProperties: - type: string - description: "Add adds the given header (name, - value) to the request before the action. It - appends to any existing values associated - with the header name. \n Input: GET /foo - HTTP/1.1 my-header: foo \n Config: add: - {\"my-header\": \"bar\"} \n Output: GET - /foo HTTP/1.1 my-header: foo my-header: - bar \n Support: Extended" - type: object - remove: - description: "Remove the given header(s) from - the HTTP request before the action. The value - of RemoveHeader is a list of HTTP header names. - Note that the header names are case-insensitive - [RFC-2616 4.2]. \n Input: GET /foo HTTP/1.1 - \ my-header1: foo my-header2: bar my-header3: - baz \n Config: remove: [\"my-header1\", - \"my-header3\"] \n Output: GET /foo HTTP/1.1 - \ my-header2: bar \n Support: Extended" - items: - type: string - maxItems: 16 - type: array - set: - additionalProperties: - type: string - description: "Set overwrites the request with - the given header (name, value) before the - action. \n Input: GET /foo HTTP/1.1 my-header: - foo \n Config: set: {\"my-header\": \"bar\"} - \n Output: GET /foo HTTP/1.1 my-header: - bar \n Support: Extended" - type: object - type: object - requestMirror: - description: "RequestMirror defines a schema for - a filter that mirrors requests. \n Support: Extended" - properties: - backendRef: - description: "BackendRef is a local object reference - to mirror matched requests to. If both BackendRef - and ServiceName are specified, ServiceName - will be given precedence. \n If the referent - cannot be found, the rule is not included - in the route. The controller should raise - the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway - status for this route should be updated with - a condition that describes the error more - specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - port: - description: "Port specifies the destination - port number to use for the backend referenced - by the ServiceName or BackendRef field. \n - If unspecified, the destination port in the - request is used when forwarding to a backendRef - or serviceName." - format: int32 - maximum: 65535 - minimum: 1 - type: integer - serviceName: - description: "ServiceName refers to the name - of the Service to mirror matched requests - to. When specified, this takes the place of - BackendRef. If both BackendRef and ServiceName - are specified, ServiceName will be given precedence. - \n If the referent cannot be found, the rule - is not included in the route. The controller - should raise the \"ResolvedRefs\" condition - on the Gateway with the \"DegradedRoutes\" - reason. The gateway status for this route - should be updated with a condition that describes - the error more specifically. \n Support: Core" - maxLength: 253 - type: string - type: object - type: - description: "Type identifies the type of filter - to apply. As with other API fields, types are - classified into three conformance levels: \n - - Core: Filter types and their corresponding configuration - defined by \"Support: Core\" in this package, - e.g. \"RequestHeaderModifier\". All implementations - must support core filters. \n - Extended: Filter - types and their corresponding configuration defined - by \"Support: Extended\" in this package, e.g. - \"RequestMirror\". Implementers are encouraged - to support extended filters. \n - Custom: 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. \n Implementers are encouraged - to define custom implementation types to extend - the core API with implementation-specific behavior." - enum: - - RequestHeaderModifier - - RequestMirror - - ExtensionRef - type: string - required: - - type - type: object - maxItems: 16 - type: array - port: - description: "Port specifies the destination port number - to use for the backend referenced by the ServiceName - or BackendRef field. If unspecified, the destination - port in the request is used when forwarding to a backendRef - or serviceName. \n Support: Core" - format: int32 - maximum: 65535 - minimum: 1 - type: integer - serviceName: - description: "ServiceName refers to the name of the Service - to forward matched requests to. When specified, this - takes the place of BackendRef. If both BackendRef and - ServiceName are specified, ServiceName will be given - precedence. \n If the referent cannot be found, the - route must be dropped from the Gateway. The controller - should raise the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway status - for this route should be updated with a condition that - describes the error more specifically. \n The protocol - to use should be specified with the AppProtocol field - on Service resources. This field was introduced in Kubernetes - 1.18. If using an earlier version of Kubernetes, a `networking.x-k8s.io/app-protocol` - annotation on the BackendPolicy resource may be used - to define the protocol. If the AppProtocol field is - available, this annotation should not be used. The AppProtocol - field, when populated, takes precedence over the annotation - in the BackendPolicy resource. For custom backends, - it is encouraged to add a semantically-equivalent field - in the Custom Resource Definition. \n Support: Core" - maxLength: 253 - type: string - weight: - default: 1 - description: "Weight specifies the proportion of HTTP - requests forwarded to the backend referenced by the - ServiceName or BackendRef field. This is computed as - weight/(sum of all weights in this ForwardTo list). - For non-zero values, there may be some epsilon from - the exact proportion defined here depending on the precision - an implementation supports. Weight is not a percentage - and the sum of weights does not need to equal 100. \n - If only one backend is specified and it has a weight - greater than 0, 100% of the traffic is forwarded to - that backend. If weight is set to 0, no traffic should - be forwarded for this entry. If unspecified, weight - defaults to 1. \n Support: Core" - format: int32 - maximum: 1000000 - minimum: 0 - type: integer - type: object - maxItems: 16 - type: array - matches: - default: - - path: - type: Prefix - value: / - description: "Matches define conditions used for matching the - rule against incoming HTTP requests. Each match is independent, - i.e. this rule will be matched if **any** one of the matches - is satisfied. \n For example, take the following matches configuration: - \n ``` matches: - path: value: \"/foo\" headers: values: - \ version: \"2\" - path: value: \"/v2/foo\" ``` \n - For a request to match against this rule, a request should - satisfy EITHER of the two conditions: \n - path prefixed with - `/foo` AND contains the header `version: \"2\"` - path prefix - of `/v2/foo` \n See the documentation for HTTPRouteMatch on - how to specify multiple match conditions that should be ANDed - together. \n If no matches are specified, the default is a - prefix path match on \"/\", which has the effect of matching - every HTTP request. \n Each client request MUST map to a maximum - of one route rule. If a request matches multiple rules, matching - precedence MUST be determined in order of the following criteria, - continuing on ties: \n * The longest matching hostname. * - The longest matching path. * The largest number of header - matches. \n If ties still exist across multiple Routes, matching - precedence MUST be determined in order of the following criteria, - continuing on ties: \n * The oldest Route based on creation - timestamp. For example, a Route with a creation timestamp - of \"2020-09-08 01:02:03\" is given precedence over a Route - with a creation timestamp of \"2020-09-08 01:02:04\". * The - Route appearing first in alphabetical order by \"/\". - For example, foo/bar is given precedence over foo/baz. \n - If ties still exist within the Route that has been given precedence, - matching precedence MUST be granted to the first matching - rule meeting the above criteria." - items: - description: "HTTPRouteMatch defines the predicate used to - match requests to a given action. Multiple match types are - ANDed together, i.e. the match will evaluate to true only - if all conditions are satisfied. \n For example, the match - below will match a HTTP request only if its path starts - with `/foo` AND it contains the `version: \"1\"` header: - \n ``` match: path: value: \"/foo\" headers: values: - \ version: \"1\" ```" - properties: - extensionRef: - description: "ExtensionRef is an optional, implementation-specific - extension to the \"match\" behavior. For example, resource - \"myroutematcher\" in group \"networking.acme.io\". - If the referent cannot be found, the rule is not included - in the route. The controller should raise the \"ResolvedRefs\" - condition on the Gateway with the \"DegradedRoutes\" - reason. The gateway status for this route should be - updated with a condition that describes the error more - specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - headers: - description: Headers specifies a HTTP request header matcher. - properties: - type: - default: Exact - description: "Type specifies how to match against - the value of the header. \n Support: Core (Exact) - \n Support: Custom (RegularExpression, ImplementationSpecific) - \n Since RegularExpression PathType has custom conformance, - implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the - implementation's documentation to determine the - supported dialect. \n HTTP Header name matching - MUST be case-insensitive (RFC 2616 - section 4.2)." - enum: - - Exact - - RegularExpression - - ImplementationSpecific - type: string - values: - additionalProperties: - type: string - description: "Values is a map of HTTP Headers to be - matched. It MUST contain at least one entry. \n - The HTTP header field name to match is the map key, - and the value of the HTTP header is the map value. - HTTP header field name matching MUST be case-insensitive. - \n Multiple match values are ANDed together, meaning, - a request must match all the specified headers to - select the route." - type: object - required: - - values - type: object - path: - default: - type: Prefix - value: / - description: Path specifies a HTTP request path matcher. - If this field is not specified, a default prefix match - on the "/" path is provided. - properties: - type: - default: Prefix - description: "Type specifies how to match against - the path Value. \n Support: Core (Exact, Prefix) - \n Support: Custom (RegularExpression, ImplementationSpecific) - \n Since RegularExpression PathType has custom conformance, - implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the - implementation's documentation to determine the - supported dialect." - enum: - - Exact - - Prefix - - RegularExpression - - ImplementationSpecific - type: string - value: - default: / - description: Value of the HTTP path to match against. - type: string - type: object - queryParams: - description: QueryParams specifies a HTTP query parameter - matcher. - properties: - type: - default: Exact - description: "Type specifies how to match against - the value of the query parameter. \n Support: Extended - (Exact) \n Support: Custom (RegularExpression, ImplementationSpecific) - \n Since RegularExpression QueryParamMatchType has - custom conformance, implementations can support - POSIX, PCRE or any other dialects of regular expressions. - Please read the implementation's documentation to - determine the supported dialect." - enum: - - Exact - - RegularExpression - - ImplementationSpecific - type: string - values: - additionalProperties: - type: string - description: "Values is a map of HTTP query parameters - to be matched. It MUST contain at least one entry. - \n The query parameter name to match is the map - key, and the value of the query parameter is the - map value. \n Multiple match values are ANDed together, - meaning, a request must match all the specified - query parameters to select the route. \n HTTP query - parameter matching MUST be case-sensitive for both - keys and values. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). - \n Note that the query parameter key MUST always - be an exact match by string comparison." - type: object - required: - - values - type: object - type: object - maxItems: 8 - type: array - type: object - maxItems: 16 - type: array - tls: - description: "TLS defines the TLS certificate to use for Hostnames - defined in this Route. This configuration only takes effect if the - AllowRouteOverride field is set to true in the associated Gateway - resource. \n Collisions can happen if multiple HTTPRoutes define - a TLS certificate for the same hostname. In such a case, conflict - resolution guiding principles apply, specifically, if hostnames - are same and two different certificates are specified then the certificate - in the oldest resource wins. \n Please note that HTTP Route-selection - takes place after the TLS Handshake (ClientHello). Due to this, - TLS certificate defined here will take precedence even if the request - has the potential to match multiple routes (in case multiple HTTPRoutes - share the same hostname). \n Support: Core" - properties: - certificateRef: - description: "CertificateRef is a reference to a Kubernetes object - that contains a TLS certificate and private key. This certificate - is used to establish a TLS handshake for requests that match - the hostname of the associated HTTPRoute. The referenced object - MUST reside in the same namespace as HTTPRoute. \n This field - is required when the TLS configuration mode of the associated - Gateway listener is set to \"Passthrough\". \n CertificateRef - can reference a standard Kubernetes resource, i.e. Secret, or - an implementation-specific custom resource. \n Support: Core - (Kubernetes Secrets) \n Support: Implementation-specific (Other - resource types)" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - required: - - certificateRef - type: object - type: object - status: - description: Status defines the current state of HTTPRoute. - properties: - gateways: - description: "Gateways is a list of Gateways that are associated with - the route, and the status of the route with respect to each Gateway. - When a Gateway selects this route, the controller that manages the - Gateway must add an entry to this list when the controller first - sees the route and should update the entry as appropriate when the - route is modified. \n A maximum of 100 Gateways will be represented - in this list. If this list is full, there may be additional Gateways - using this Route that are not included in the list. An empty list - means the route has not been admitted by any Gateway." - items: - description: RouteGatewayStatus describes the status of a route - with respect to an associated Gateway. - properties: - conditions: - description: Conditions describes the status of the route with - respect to the Gateway. The "Admitted" condition must always - be specified by controllers to indicate whether the route - has been admitted or rejected by the Gateway, and why. Note - that the route's availability is also subject to the Gateway's - own status conditions and listener status. - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - maxItems: 8 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - gatewayRef: - description: GatewayRef is a reference to a Gateway object that - is associated with the route. - properties: - controller: - description: "Controller is a domain/path string that indicates - the controller implementing the Gateway. This corresponds - with the controller field on GatewayClass. \n Example: - \"acme.io/gateway-controller\". \n The format of this - field is DOMAIN \"/\" PATH, where DOMAIN and PATH are - valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." - maxLength: 253 - 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 referent. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - namespace - type: object - required: - - gatewayRef - type: object - maxItems: 100 - type: array - required: - - gateways - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/docs/content/reference/dynamic-configuration/networking.x-k8s.io_tcproutes.yaml b/docs/content/reference/dynamic-configuration/networking.x-k8s.io_tcproutes.yaml deleted file mode 100644 index c9b62c458..000000000 --- a/docs/content/reference/dynamic-configuration/networking.x-k8s.io_tcproutes.yaml +++ /dev/null @@ -1,401 +0,0 @@ - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - name: tcproutes.networking.x-k8s.io -spec: - group: networking.x-k8s.io - names: - categories: - - gateway-api - kind: TCPRoute - listKind: TCPRouteList - plural: tcproutes - singular: tcproute - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: TCPRoute is the Schema for the TCPRoute resource. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of TCPRoute. - properties: - gateways: - default: - allow: SameNamespace - description: Gateways defines which Gateways can use this Route. - properties: - allow: - default: SameNamespace - description: 'Allow indicates which Gateways will be allowed to - use this route. Possible values are: * All: Gateways in any - namespace can use this route. * FromList: Only Gateways specified - in GatewayRefs may use this route. * SameNamespace: Only Gateways - in the same namespace may use this route.' - enum: - - All - - FromList - - SameNamespace - type: string - gatewayRefs: - description: GatewayRefs must be specified when Allow is set to - "FromList". In that case, only Gateways referenced in this list - will be allowed to use this route. This field is ignored for - other values of "Allow". - items: - description: GatewayReference identifies a Gateway in a specified - namespace. - properties: - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace is the namespace of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - namespace - type: object - type: array - type: object - rules: - description: Rules are a list of TCP matchers and actions. - items: - description: TCPRouteRule is the configuration for a given rule. - properties: - forwardTo: - description: ForwardTo defines the backend(s) where matching - requests should be sent. - items: - description: RouteForwardTo defines how a Route should forward - a request. - properties: - backendRef: - description: "BackendRef is a reference to a backend to - forward matched requests to. If both BackendRef and - ServiceName are specified, ServiceName will be given - precedence. \n If the referent cannot be found, the - rule is not included in the route. The controller should - raise the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway status - for this route should be updated with a condition that - describes the error more specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - port: - description: "Port specifies the destination port number - to use for the backend referenced by the ServiceName - or BackendRef field. If unspecified, the destination - port in the request is used when forwarding to a backendRef - or serviceName. \n Support: Core" - format: int32 - maximum: 65535 - minimum: 1 - type: integer - serviceName: - description: "ServiceName refers to the name of the Service - to forward matched requests to. When specified, this - takes the place of BackendRef. If both BackendRef and - ServiceName are specified, ServiceName will be given - precedence. \n If the referent cannot be found, the - rule is not included in the route. The controller should - raise the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway status - for this route should be updated with a condition that - describes the error more specifically. \n The protocol - to use is defined using AppProtocol field (introduced - in Kubernetes 1.18) in the Service resource. In the - absence of the AppProtocol field a `networking.x-k8s.io/app-protocol` - annotation on the BackendPolicy resource may be used - to define the protocol. If the AppProtocol field is - available, this annotation should not be used. The AppProtocol - field, when populated, takes precedence over the annotation - in the BackendPolicy resource. For custom backends, - it is encouraged to add a semantically-equivalent field - in the Custom Resource Definition. \n Support: Core" - maxLength: 253 - type: string - weight: - default: 1 - description: "Weight specifies the proportion of HTTP - requests forwarded to the backend referenced by the - ServiceName or BackendRef field. This is computed as - weight/(sum of all weights in this ForwardTo list). - For non-zero values, there may be some epsilon from - the exact proportion defined here depending on the precision - an implementation supports. Weight is not a percentage - and the sum of weights does not need to equal 100. \n - If only one backend is specified and it has a weight - greater than 0, 100% of the traffic is forwarded to - that backend. If weight is set to 0, no traffic should - be forwarded for this entry. If unspecified, weight - defaults to 1. \n Support: Extended" - format: int32 - maximum: 1000000 - minimum: 0 - type: integer - type: object - maxItems: 16 - minItems: 1 - type: array - matches: - description: "Matches define conditions used for matching the - rule against incoming TCP connections. Each match is independent, - i.e. this rule will be matched if **any** one of the matches - is satisfied. If unspecified (i.e. empty), this Rule will - match all requests for the associated Listener. \n Each client - request MUST map to a maximum of one route rule. If a request - matches multiple rules, matching precedence MUST be determined - in order of the following criteria, continuing on ties: \n - * The most specific match specified by ExtensionRef. Each - implementation that supports ExtensionRef may have different - ways of determining the specificity of the referenced extension. - \n If ties still exist across multiple Routes, matching precedence - MUST be determined in order of the following criteria, continuing - on ties: \n * The oldest Route based on creation timestamp. - For example, a Route with a creation timestamp of \"2020-09-08 - 01:02:03\" is given precedence over a Route with a creation - timestamp of \"2020-09-08 01:02:04\". * The Route appearing - first in alphabetical order by \"/\". For - example, foo/bar is given precedence over foo/baz. \n If - ties still exist within the Route that has been given precedence, - matching precedence MUST be granted to the first matching - rule meeting the above criteria." - items: - description: TCPRouteMatch defines the predicate used to match - connections to a given action. - properties: - extensionRef: - description: "ExtensionRef is an optional, implementation-specific - extension to the \"match\" behavior. For example, resource - \"mytcproutematcher\" in group \"networking.acme.io\". - If the referent cannot be found, the rule is not included - in the route. The controller should raise the \"ResolvedRefs\" - condition on the Gateway with the \"DegradedRoutes\" - reason. The gateway status for this route should be - updated with a condition that describes the error more - specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - type: object - maxItems: 8 - type: array - required: - - forwardTo - type: object - maxItems: 16 - minItems: 1 - type: array - required: - - rules - type: object - status: - description: Status defines the current state of TCPRoute. - properties: - gateways: - description: "Gateways is a list of Gateways that are associated with - the route, and the status of the route with respect to each Gateway. - When a Gateway selects this route, the controller that manages the - Gateway must add an entry to this list when the controller first - sees the route and should update the entry as appropriate when the - route is modified. \n A maximum of 100 Gateways will be represented - in this list. If this list is full, there may be additional Gateways - using this Route that are not included in the list. An empty list - means the route has not been admitted by any Gateway." - items: - description: RouteGatewayStatus describes the status of a route - with respect to an associated Gateway. - properties: - conditions: - description: Conditions describes the status of the route with - respect to the Gateway. The "Admitted" condition must always - be specified by controllers to indicate whether the route - has been admitted or rejected by the Gateway, and why. Note - that the route's availability is also subject to the Gateway's - own status conditions and listener status. - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - maxItems: 8 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - gatewayRef: - description: GatewayRef is a reference to a Gateway object that - is associated with the route. - properties: - controller: - description: "Controller is a domain/path string that indicates - the controller implementing the Gateway. This corresponds - with the controller field on GatewayClass. \n Example: - \"acme.io/gateway-controller\". \n The format of this - field is DOMAIN \"/\" PATH, where DOMAIN and PATH are - valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." - maxLength: 253 - 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 referent. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - namespace - type: object - required: - - gatewayRef - type: object - maxItems: 100 - type: array - required: - - gateways - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/docs/content/reference/dynamic-configuration/networking.x-k8s.io_tlsroutes.yaml b/docs/content/reference/dynamic-configuration/networking.x-k8s.io_tlsroutes.yaml deleted file mode 100644 index 31d10f2f6..000000000 --- a/docs/content/reference/dynamic-configuration/networking.x-k8s.io_tlsroutes.yaml +++ /dev/null @@ -1,437 +0,0 @@ - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - name: tlsroutes.networking.x-k8s.io -spec: - group: networking.x-k8s.io - names: - categories: - - gateway-api - kind: TLSRoute - listKind: TLSRouteList - plural: tlsroutes - singular: tlsroute - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: "The TLSRoute resource is similar to TCPRoute, but can be configured - to match against TLS-specific metadata. This allows more flexibility in - matching streams for a given TLS listener. \n If you need to forward traffic - to a single target for a TLS listener, you could choose to use a TCPRoute - with a TLS listener." - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of TLSRoute. - properties: - gateways: - default: - allow: SameNamespace - description: Gateways defines which Gateways can use this Route. - properties: - allow: - default: SameNamespace - description: 'Allow indicates which Gateways will be allowed to - use this route. Possible values are: * All: Gateways in any - namespace can use this route. * FromList: Only Gateways specified - in GatewayRefs may use this route. * SameNamespace: Only Gateways - in the same namespace may use this route.' - enum: - - All - - FromList - - SameNamespace - type: string - gatewayRefs: - description: GatewayRefs must be specified when Allow is set to - "FromList". In that case, only Gateways referenced in this list - will be allowed to use this route. This field is ignored for - other values of "Allow". - items: - description: GatewayReference identifies a Gateway in a specified - namespace. - properties: - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace is the namespace of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - namespace - type: object - type: array - type: object - rules: - description: Rules are a list of TLS matchers and actions. - items: - description: TLSRouteRule is the configuration for a given rule. - properties: - forwardTo: - description: ForwardTo defines the backend(s) where matching - requests should be sent. - items: - description: RouteForwardTo defines how a Route should forward - a request. - properties: - backendRef: - description: "BackendRef is a reference to a backend to - forward matched requests to. If both BackendRef and - ServiceName are specified, ServiceName will be given - precedence. \n If the referent cannot be found, the - rule is not included in the route. The controller should - raise the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway status - for this route should be updated with a condition that - describes the error more specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - port: - description: "Port specifies the destination port number - to use for the backend referenced by the ServiceName - or BackendRef field. If unspecified, the destination - port in the request is used when forwarding to a backendRef - or serviceName. \n Support: Core" - format: int32 - maximum: 65535 - minimum: 1 - type: integer - serviceName: - description: "ServiceName refers to the name of the Service - to forward matched requests to. When specified, this - takes the place of BackendRef. If both BackendRef and - ServiceName are specified, ServiceName will be given - precedence. \n If the referent cannot be found, the - rule is not included in the route. The controller should - raise the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway status - for this route should be updated with a condition that - describes the error more specifically. \n The protocol - to use is defined using AppProtocol field (introduced - in Kubernetes 1.18) in the Service resource. In the - absence of the AppProtocol field a `networking.x-k8s.io/app-protocol` - annotation on the BackendPolicy resource may be used - to define the protocol. If the AppProtocol field is - available, this annotation should not be used. The AppProtocol - field, when populated, takes precedence over the annotation - in the BackendPolicy resource. For custom backends, - it is encouraged to add a semantically-equivalent field - in the Custom Resource Definition. \n Support: Core" - maxLength: 253 - type: string - weight: - default: 1 - description: "Weight specifies the proportion of HTTP - requests forwarded to the backend referenced by the - ServiceName or BackendRef field. This is computed as - weight/(sum of all weights in this ForwardTo list). - For non-zero values, there may be some epsilon from - the exact proportion defined here depending on the precision - an implementation supports. Weight is not a percentage - and the sum of weights does not need to equal 100. \n - If only one backend is specified and it has a weight - greater than 0, 100% of the traffic is forwarded to - that backend. If weight is set to 0, no traffic should - be forwarded for this entry. If unspecified, weight - defaults to 1. \n Support: Extended" - format: int32 - maximum: 1000000 - minimum: 0 - type: integer - type: object - maxItems: 16 - minItems: 1 - type: array - matches: - description: "Matches define conditions used for matching the - rule against incoming TLS connections. Each match is independent, - i.e. this rule will be matched if **any** one of the matches - is satisfied. If unspecified (i.e. empty), this Rule will - match all requests for the associated Listener. \n Each client - request MUST map to a maximum of one route rule. If a request - matches multiple rules, matching precedence MUST be determined - in order of the following criteria, continuing on ties: \n - * The longest matching SNI. * The longest matching precise - SNI (without a wildcard). This means that \"b.example.com\" - should be given precedence over \"*.example.com\". * The most - specific match specified by ExtensionRef. Each implementation - \ that supports ExtensionRef may have different ways of determining - the specificity of the referenced extension. \n If ties - still exist across multiple Routes, matching precedence MUST - be determined in order of the following criteria, continuing - on ties: \n * The oldest Route based on creation timestamp. - For example, a Route with a creation timestamp of \"2020-09-08 - 01:02:03\" is given precedence over a Route with a creation - timestamp of \"2020-09-08 01:02:04\". * The Route appearing - first in alphabetical order by \"/\". For - example, foo/bar is given precedence over foo/baz. \n If - ties still exist within the Route that has been given precedence, - matching precedence MUST be granted to the first matching - rule meeting the above criteria." - items: - description: TLSRouteMatch defines the predicate used to match - connections to a given action. - properties: - extensionRef: - description: "ExtensionRef is an optional, implementation-specific - extension to the \"match\" behavior. For example, resource - \"mytlsroutematcher\" in group \"networking.acme.io\". - If the referent cannot be found, the rule is not included - in the route. The controller should raise the \"ResolvedRefs\" - condition on the Gateway with the \"DegradedRoutes\" - reason. The gateway status for this route should be - updated with a condition that describes the error more - specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - snis: - description: "SNIs defines a set of SNI names that should - match against the SNI attribute of TLS ClientHello message - in TLS handshake. \n SNI can be \"precise\" which is - a domain name without the terminating dot of a network - host (e.g. \"foo.example.com\") or \"wildcard\", which - is a domain name prefixed with a single wildcard label - (e.g. `*.example.com`). The wildcard character `*` must - appear by itself as the first DNS label and matches - only a single label. You cannot have a wildcard label - by itself (e.g. Host == `*`). \n Requests will be matched - against the Host field in the following order: \n 1. - If SNI is precise, the request matches this rule if - the SNI in ClientHello is equal to one of the defined - SNIs. 2. If SNI is a wildcard, then the request matches - this rule if the SNI is to equal to the suffix (removing - the first label) of the wildcard rule. 3. If SNIs - is unspecified, all requests associated with the gateway - TLS listener will match. This can be used to define - a default backend for a TLS listener. \n Support: - Core" - items: - description: Hostname is used to specify a hostname - that should be matched. - maxLength: 253 - minLength: 1 - type: string - maxItems: 16 - type: array - type: object - maxItems: 8 - type: array - required: - - forwardTo - type: object - maxItems: 16 - minItems: 1 - type: array - required: - - rules - type: object - status: - description: Status defines the current state of TLSRoute. - properties: - gateways: - description: "Gateways is a list of Gateways that are associated with - the route, and the status of the route with respect to each Gateway. - When a Gateway selects this route, the controller that manages the - Gateway must add an entry to this list when the controller first - sees the route and should update the entry as appropriate when the - route is modified. \n A maximum of 100 Gateways will be represented - in this list. If this list is full, there may be additional Gateways - using this Route that are not included in the list. An empty list - means the route has not been admitted by any Gateway." - items: - description: RouteGatewayStatus describes the status of a route - with respect to an associated Gateway. - properties: - conditions: - description: Conditions describes the status of the route with - respect to the Gateway. The "Admitted" condition must always - be specified by controllers to indicate whether the route - has been admitted or rejected by the Gateway, and why. Note - that the route's availability is also subject to the Gateway's - own status conditions and listener status. - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - maxItems: 8 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - gatewayRef: - description: GatewayRef is a reference to a Gateway object that - is associated with the route. - properties: - controller: - description: "Controller is a domain/path string that indicates - the controller implementing the Gateway. This corresponds - with the controller field on GatewayClass. \n Example: - \"acme.io/gateway-controller\". \n The format of this - field is DOMAIN \"/\" PATH, where DOMAIN and PATH are - valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." - maxLength: 253 - 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 referent. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - namespace - type: object - required: - - gatewayRef - type: object - maxItems: 100 - type: array - required: - - gateways - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/docs/content/routing/providers/kubernetes-gateway.md b/docs/content/routing/providers/kubernetes-gateway.md index 43adff0db..b679ba95b 100644 --- a/docs/content/routing/providers/kubernetes-gateway.md +++ b/docs/content/routing/providers/kubernetes-gateway.md @@ -1,7 +1,6 @@ # Traefik & Kubernetes -The Kubernetes Gateway API, The Experimental Way. -{: .subtitle } +The Kubernetes Gateway API, The Experimental Way. {: .subtitle } ## Configuration Examples @@ -28,183 +27,180 @@ The Kubernetes Gateway API, The Experimental Way. ### Custom Resource Definition (CRD) * You can find an exhaustive list, of the custom resources and their attributes in -[the reference page](../../reference/dynamic-configuration/kubernetes-gateway.md) or in the Kubernetes Sigs `Gateway API` [repository](https://github.com/kubernetes-sigs/gateway-api). -* Validate that [the prerequisites](../../providers/kubernetes-gateway.md#configuration-requirements) are fulfilled before using the Traefik Kubernetes Gateway Provider. - + [the reference page](../../reference/dynamic-configuration/kubernetes-gateway.md) or in the Kubernetes + Sigs `Gateway API` [repository](https://github.com/kubernetes-sigs/gateway-api). +* Validate that [the prerequisites](../../providers/kubernetes-gateway.md#configuration-requirements) are fulfilled + before using the Traefik Kubernetes Gateway Provider. + You can find an excerpt of the supported Kubernetes Gateway API resources in the table below: | Kind | Purpose | Concept Behind | |------------------------------------|---------------------------------------------------------------------------|--------------------------------------------------------------------------------------| -| [GatewayClass](#kind-gatewayclass) | Defines a set of Gateways that share a common configuration and behaviour | [GatewayClass](https://gateway-api.sigs.k8s.io/v1alpha1/api-types/gatewayclass) | -| [Gateway](#kind-gateway) | Describes how traffic can be translated to Services within the cluster | [Gateway](https://gateway-api.sigs.k8s.io/v1alpha1/api-types/gateway) | -| [HTTPRoute](#kind-httproute) | HTTP rules for mapping requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/v1alpha1/api-types/httproute) | +| [GatewayClass](#kind-gatewayclass) | Defines a set of Gateways that share a common configuration and behaviour | [GatewayClass](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/gatewayclass) | +| [Gateway](#kind-gateway) | Describes how traffic can be translated to Services within the cluster | [Gateway](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/gateway) | +| [HTTPRoute](#kind-httproute) | HTTP rules for mapping requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/httproute) | | [TCPRoute](#kind-tcproute) | Allows mapping TCP requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/concepts/api-overview/#tcproute-and-udproute)| | [TLSRoute](#kind-tlsroute) | Allows mapping TLS requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/concepts/api-overview/#tcproute-and-udproute)| ### Kind: `GatewayClass` -`GatewayClass` is cluster-scoped resource defined by the infrastructure provider. This resource represents a class of Gateways that can be instantiated. -More details on the GatewayClass [official documentation](https://gateway-api.sigs.k8s.io/v1alpha1/api-types/gatewayclass/). +`GatewayClass` is cluster-scoped resource defined by the infrastructure provider. This resource represents a class of +Gateways that can be instantiated. More details on the +GatewayClass [official documentation](https://gateway-api.sigs.k8s.io/v1alpha1/api-types/gatewayclass/). The `GatewayClass` should be declared by the infrastructure provider, otherwise please register the `GatewayClass` -[definition](../../reference/dynamic-configuration/kubernetes-gateway.md#definitions) in the Kubernetes cluster before +[definition](../../reference/dynamic-configuration/kubernetes-gateway.md#definitions) in the Kubernetes cluster before creating `GatewayClass` objects. !!! info "Declaring GatewayClass" ```yaml + apiVersion: gateway.networking.k8s.io/v1alpha2 kind: GatewayClass - apiVersion: networking.x-k8s.io/v1alpha1 metadata: name: my-gateway-class spec: # Controller is a domain/path string that indicates # the controller that is managing Gateways of this class. - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller ``` ### Kind: `Gateway` -A `Gateway` is 1:1 with the life cycle of the configuration of infrastructure. When a user creates a Gateway, -some load balancing infrastructure is provisioned or configured by the GatewayClass controller. -More details on the Gateway [official documentation](https://gateway-api.sigs.k8s.io/v1alpha1/api-types/gateway/). +A `Gateway` is 1:1 with the life cycle of the configuration of infrastructure. When a user creates a Gateway, some load +balancing infrastructure is provisioned or configured by the GatewayClass controller. More details on the +Gateway [official documentation](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/gateway/). Register the `Gateway` [definition](../../reference/dynamic-configuration/kubernetes-gateway.md#definitions) in the Kubernetes cluster before creating `Gateway` objects. Depending on the Listener Protocol, different modes and Route types are supported. -| Listener Protocol | TLS Mode | Route Type Supported | -|-------------------|----------------|------------------------------| -| TCP | Not applicable | [TCPRoute](#kind-tcproute) | -| TLS | Passthrough | [TLSRoute](#kind-tlsroute) | -| TLS | Terminate | [TCPRoute](#kind-tcproute) | -| HTTP | Not applicable | [HTTPRoute](#kind-httproute) | -| HTTPS | Terminate | [HTTPRoute](#kind-httproute) | +| Listener Protocol | TLS Mode | Route Type Supported | +|-------------------|----------------|--------------------------------------------------------| +| TCP | Not applicable | [TCPRoute](#kind-tcproute) | +| TLS | Passthrough | [TLSRoute](#kind-tlsroute), [TCPRoute](#kind-tcproute) | +| TLS | Terminate | [TLSRoute](#kind-tlsroute), [TCPRoute](#kind-tcproute) | +| HTTP | Not applicable | [HTTPRoute](#kind-httproute) | +| HTTPS | Terminate | [HTTPRoute](#kind-httproute) | !!! info "Declaring Gateway" ```yaml tab="HTTP Listener" + apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway - apiVersion: networking.x-k8s.io/v1alpha1 metadata: name: my-http-gateway namespace: default spec: gatewayClassName: my-gateway-class # [1] listeners: # [2] - - protocol: HTTP # [3] - port: 80 # [4] - routes: # [8] - kind: HTTPRoute # [9] + - name: http # [3] + protocol: HTTP # [4] + port: 80 # [5] + allowedRoutes: # [9] + kinds: + - kind: HTTPRoute # [10] namespaces: - from: Selector # [10] - selector: # [11] + from: Selector # [11] + selector: # [12] matchLabels: app: foo - selector: # [12] - matchLabels: - app: foo ``` ```yaml tab="HTTPS Listener" + apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway - apiVersion: networking.x-k8s.io/v1alpha1 metadata: name: my-https-gateway namespace: default spec: gatewayClassName: my-gateway-class # [1] listeners: # [2] - - protocol: HTTPS # [3] - port: 443 # [4] - tls: # [6] - certificateRef: # [7] - group: "core" - kind: "Secret" - name: "mysecret" - routes: # [8] - kind: HTTPRoute # [9] + - name: https # [3] + protocol: HTTPS # [4] + port: 443 # [5] + tls: # [7] + certificateRefs: # [8] + - kind: "Secret" + name: "mysecret" + allowedRoutes: # [9] + kinds: + - kind: HTTPSRoute # [10] namespaces: - from: Selector # [10] - selector: # [11] + from: Selector # [11] + selector: # [12] matchLabels: app: foo - selector: # [12] - matchLabels: - app: foo ``` ```yaml tab="TCP Listener" + apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway - apiVersion: networking.x-k8s.io/v1alpha1 metadata: name: my-tcp-gateway namespace: default spec: gatewayClassName: my-gateway-class # [1] listeners: # [2] - - protocol: TCP # [3] - port: 8000 # [4] - routes: # [8] - kind: TCPRoute # [9] + - name: tcp # [3] + protocol: TCP # [4] + port: 8000 # [5] + allowedRoutes: # [9] + kinds: + - kind: TCPRoute # [10] namespaces: - from: Selector # [10] - selector: # [11] + from: Selector # [11] + selector: # [12] matchLabels: app: footcp - selector: # [12] - matchLabels: - app: footcp ``` ```yaml tab="TLS Listener" + apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway - apiVersion: networking.x-k8s.io/v1alpha1 metadata: name: my-tls-gateway namespace: default spec: gatewayClassName: my-gateway-class # [1] listeners: # [2] - - protocol: TLS # [3] - port: 443 # [4] - hostname: foo.com # [5] - tls: # [6] - certificateRef: # [7] - group: "core" - kind: "Secret" - name: "mysecret" - routes: # [8] - kind: TLSRoute # [9] + - name: tls # [3] + protocol: TLS # [4] + port: 443 # [5] + hostname: foo.com # [6] + tls: # [7] + certificateRefs: # [8] + - kind: "Secret" + name: "mysecret" + allowedRoutes: # [9] + kinds: + - kind: TLSRoute # [10] namespaces: - from: Selector # [10] - selector: # [11] + from: Selector # [11] + selector: # [12] matchLabels: app: footcp - selector: # [12] - matchLabels: - app: footcp ``` | Ref | Attribute | Description | |------|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| | [1] | `gatewayClassName` | GatewayClassName used for this Gateway. This is the name of a GatewayClass resource. | | [2] | `listeners` | Logical endpoints that are bound on this Gateway's addresses. At least one Listener MUST be specified. | -| [3] | `protocol` | The network protocol this listener expects to receive (only HTTP and HTTPS are implemented). | -| [4] | `port` | The network port. | -| [5] | `hostname` | Hostname specifies the virtual hostname to match for protocol types that define this concept. When unspecified, “”, or *, all hostnames are matched. | -| [6] | `tls` | TLS configuration for the Listener. This field is required if the Protocol field is "HTTPS" or "TLS" and ignored otherwise. | -| [7] | `certificateRef` | The reference to Kubernetes object that contains a TLS certificate and private key. | -| [8] | `routes` | A schema for associating routes with the Listener using selectors. | -| [9] | `kind` | The kind of the referent. | -| [10] | `from` | From indicates in which namespaces the Routes will be selected for this Gateway. Possible values are `All`, `Same` and `Selector` (Defaults to `Same`). | -| [11] | `selector` | Selector must be specified when From is set to `Selector`. In that case, only Routes in Namespaces matching this Selector will be selected by this Gateway. | -| [12] | `selector` | Selector specifies a set of route labels used for selecting routes to associate with the Gateway. An empty Selector matches all routes. | +| [3] | `name` | Name of the Listener. | +| [4] | `protocol` | The network protocol this listener expects to receive (only HTTP and HTTPS are implemented). | +| [5] | `port` | The network port. | +| [6] | `hostname` | Hostname specifies the virtual hostname to match for protocol types that define this concept. When unspecified, “”, or *, all hostnames are matched. | +| [7] | `tls` | TLS configuration for the Listener. This field is required if the Protocol field is "HTTPS" or "TLS" and ignored otherwise. | +| [8] | `certificateRefs` | The references to Kubernetes objects that contains TLS certificates and private keys (only one reference to a Kubernetes Secret is supported). | +| [9] | `allowedRoutes` | Defines the types of routes that MAY be attached to a Listener and the trusted namespaces where those Route resources MAY be present. | +| [10] | `kind` | The kind of the Route. | +| [11] | `from` | From indicates in which namespaces the Routes will be selected for this Gateway. Possible values are `All`, `Same` and `Selector` (Defaults to `Same`). | +| [12] | `selector` | Selector must be specified when From is set to `Selector`. In that case, only Routes in Namespaces matching this Selector will be selected by this Gateway. | ### Kind: `HTTPRoute` -`HTTPRoute` defines HTTP rules for mapping requests from a `Gateway` to Kubernetes Services. +`HTTPRoute` defines HTTP rules for mapping requests from a `Gateway` to Kubernetes Services. Register the `HTTPRoute` [definition](../../reference/dynamic-configuration/kubernetes-gateway.md#definitions) in the Kubernetes cluster before creating `HTTPRoute` objects. @@ -212,61 +208,60 @@ Kubernetes cluster before creating `HTTPRoute` objects. !!! info "Declaring HTTPRoute" ```yaml + apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute - apiVersion: networking.x-k8s.io/v1alpha1 metadata: - name: http-app-1 + name: http-app namespace: default - labels: # [1] - app: foo spec: - hostnames: # [2] - - "whoami" - rules: # [3] - - matches: # [4] - - path: # [5] - type: Exact # [6] - value: /bar # [7] - - headers: # [8] + parentRefs: # [1] + - name: my-tcp-gateway # [2] + namespace: default # [3] + sectionName: tcp # [4] + hostnames: # [5] + - whoami + rules: # [6] + - matches: # [7] + - path: # [8] type: Exact # [9] - values: # [10] - foo: bar - forwardTo: # [11] - - serviceName: whoami # [12] - weight: 1 # [13] - port: 80 # [14] - - backendRef: # [15] - group: traefik.containo.us # [16] - kind: TraefikService # [17] - name: api@internal # [18] - port: 80 - weight: 1 + value: /bar # [10] + - headers: # [11] + name: foo # [12] + value: bar # [13] + - backendRefs: # [14] + - name: whoamitcp # [15] + weight: 1 # [16] + port: 8080 # [17] + - name: api@internal + group: traefik.containo.us # [18] + kind: TraefikService # [19] ``` -| Ref | Attribute | Description | -|------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [1] | `labels` | Labels to match with the `Gateway` labelselector. | -| [2] | `hostnames` | A set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request. | -| [3] | `rules` | A list of HTTP matchers, filters and actions. | -| [4] | `matches` | Conditions used for matching the rule against incoming HTTP requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied. | -| [5] | `path` | An HTTP request path matcher. If this field is not specified, a default prefix match on the "/" path is provided. | -| [6] | `type` | Type of match against the path Value (supported types: `Exact`, `Prefix`). | -| [7] | `value` | The value of the HTTP path to match against. | -| [8] | `headers` | Conditions to select a HTTP route by matching HTTP request headers. | -| [9] | `type` | Type of match for the HTTP request header match against the `values` (supported types: `Exact`). | -| [10] | `values` | A map of HTTP Headers to be matched. It MUST contain at least one entry. | -| [11] | `forwardTo` | The upstream target(s) where the request should be sent. | -| [12] | `serviceName` | The name of the referent service. | -| [13] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). | -| [14] | `port` | The port of the referent service. | -| [15] | `backendRef` | The BackendRef is a reference to a backend (API object within a known namespace) to forward matched requests to. If both BackendRef and ServiceName are specified, ServiceName will be given precedence. Only `TraefikService` is supported. | -| [16] | `group` | Group is the group of the referent. Only `traefik.containo.us` value is supported. | -| [17] | `kind` | Kind is kind of the referent. Only `TraefikService` value is supported. | -| [18] | `name` | Name is the name of the referent. | +| Ref | Attribute | Description | +|------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [1] | `parentRefs` | References the resources (usually Gateways) that a Route wants to be attached to. | +| [2] | `name` | Name of the referent. | +| [3] | `namespace` | Namespace of the referent. When unspecified (or empty string), this refers to the local namespace of the Route. | +| [4] | `sectionName` | Name of a section within the target resource (the Listener name). | +| [5] | `hostnames` | A set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request. | +| [6] | `rules` | A list of HTTP matchers, filters and actions. | +| [7] | `matches` | Conditions used for matching the rule against incoming HTTP requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied. | +| [8] | `path` | An HTTP request path matcher. If this field is not specified, a default prefix match on the "/" path is provided. | +| [9] | `type` | Type of match against the path Value (supported types: `Exact`, `Prefix`). | +| [10] | `value` | The value of the HTTP path to match against. | +| [11] | `headers` | Conditions to select a HTTP route by matching HTTP request headers. | +| [12] | `type` | Type of match for the HTTP request header match against the `values` (supported types: `Exact`). | +| [13] | `value` | A map of HTTP Headers to be matched. It MUST contain at least one entry. | +| [14] | `backendRefs` | Defines the backend(s) where matching requests should be sent. | +| [15] | `name` | The name of the referent service. | +| [16] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). | +| [17] | `port` | The port of the referent service. | +| [18] | `group` | Group is the group of the referent. Only `traefik.containo.us` and `gateway.networking.k8s.io` values are supported. | +| [19] | `kind` | Kind is kind of the referent. Only `TraefikService` and `Service` values are supported. | ### Kind: `TCPRoute` -`TCPRoute` allows mapping TCP requests from a `Gateway` to Kubernetes Services +`TCPRoute` allows mapping TCP requests from a `Gateway` to Kubernetes Services. Register the `TCPRoute` [definition](../../reference/dynamic-configuration/kubernetes-gateway.md#definitions) in the Kubernetes cluster before creating `TCPRoute` objects. @@ -274,76 +269,83 @@ Kubernetes cluster before creating `TCPRoute` objects. !!! info "Declaring TCPRoute" ```yaml + apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TCPRoute - apiVersion: networking.x-k8s.io/v1alpha1 metadata: - name: tcp-app-1 + name: tcp-app namespace: default - labels: # [1] - app: tcp-app-1 spec: - rules: # [2] - - forwardTo: # [3] - - serviceName: whoamitcp # [4] - weight: 1 # [5] - port: 8080 # [6] - - backendRef: # [7] - group: traefik.containo.us # [8] - kind: TraefikService # [9] - name: api@internal # [10] + parentRefs: # [1] + - name: my-tcp-gateway # [2] + namespace: default # [3] + sectionName: tcp # [4] + rules: # [5] + - backendRefs: # [6] + - name: whoamitcp # [7] + weight: 1 # [8] + port: 8080 # [9] + - name: api@internal + group: traefik.containo.us # [10] + kind: TraefikService # [11] ``` -| Ref | Attribute | Description | -|------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [1] | `labels` | Labels to match with the `Gateway` labelselector. | -| [2] | `rules` | Rules are a list of TCP matchers and actions. | -| [3] | `forwardTo` | The upstream target(s) where the request should be sent. | -| [4] | `serviceName` | The name of the referent service. | -| [5] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). | -| [6] | `port` | The port of the referent service. | -| [7] | `backendRef` | The BackendRef is a reference to a backend (API object within a known namespace) to forward matched requests to. If both BackendRef and ServiceName are specified, ServiceName will be given precedence. Only `TraefikService` is supported. | -| [8] | `group` | Group is the group of the referent. Only `traefik.containo.us` value is supported. | -| [9] | `kind` | Kind is kind of the referent. Only `TraefikService` value is supported. | -| [10] | `name` | Name is the name of the referent. | +| Ref | Attribute | Description | +|------|---------------|----------------------------------------------------------------------------------------------------------------------| +| [1] | `parentRefs` | References the resources (usually Gateways) that a Route wants to be attached to. | +| [2] | `name` | Name of the referent. | +| [3] | `namespace` | Namespace of the referent. When unspecified (or empty string), this refers to the local namespace of the Route. | +| [4] | `sectionName` | Name of a section within the target resource (the Listener name). | +| [5] | `rules` | Rules are a list of TCP matchers and actions. | +| [6] | `backendRefs` | Defines the backend(s) where matching requests should be sent. | +| [7] | `name` | The name of the referent service. | +| [8] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). | +| [9] | `port` | The port of the referent service. | +| [10] | `group` | Group is the group of the referent. Only `traefik.containo.us` and `gateway.networking.k8s.io` values are supported. | +| [11] | `kind` | Kind is kind of the referent. Only `TraefikService` and `Service` values are supported. | ### Kind: `TLSRoute` -`TLSRoute` allows mapping TLS requests from a `Gateway` to Kubernetes Services +`TLSRoute` allows mapping TLS requests from a `Gateway` to Kubernetes Services. Register the `TLSRoute` [definition](../../reference/dynamic-configuration/kubernetes-gateway.md#definitions) in the Kubernetes cluster before creating `TLSRoute` objects. -!!! info "Declaring TCPRoute" +!!! info "Declaring TLSRoute" ```yaml + apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TLSRoute - apiVersion: networking.x-k8s.io/v1alpha1 metadata: - name: tls-app-1 + name: tls-app namespace: default - labels: # [1] - app: tls-app-1 spec: - rules: # [2] - - forwardTo: # [3] - - serviceName: whoamitcp # [4] - weight: 1 # [5] - port: 8080 # [6] - - backendRef: # [7] - group: traefik.containo.us # [8] - kind: TraefikService # [9] - name: api@internal # [10] + parentRefs: # [1] + - name: my-tls-gateway # [2] + namespace: default # [3] + sectionName: tcp # [4] + hostnames: # [5] + - whoami + rules: # [6] + - backendRefs: # [7] + - name: whoamitcp # [8] + weight: 1 # [9] + port: 8080 # [10] + - name: api@internal + group: traefik.containo.us # [11] + kind: TraefikService # [12] ``` -| Ref | Attribute | Description | -|------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [1] | `labels` | Labels to match with the `Gateway` labelselector. | -| [2] | `rules` | Rules are a list of TCP matchers and actions. | -| [3] | `forwardTo` | The upstream target(s) where the request should be sent. | -| [4] | `serviceName` | The name of the referent service. | -| [5] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). | -| [6] | `port` | The port of the referent service. | -| [7] | `backendRef` | The BackendRef is a reference to a backend (API object within a known namespace) to forward matched requests to. If both BackendRef and ServiceName are specified, ServiceName will be given precedence. Only `TraefikService` is supported. | -| [8] | `group` | Group is the group of the referent. Only `traefik.containo.us` value is supported. | -| [9] | `kind` | Kind is kind of the referent. Only `TraefikService` value is supported. | -| [10] | `name` | Name is the name of the referent. | +| Ref | Attribute | Description | +|------|---------------|----------------------------------------------------------------------------------------------------------------------| +| [1] | `parentRefs` | References the resources (usually Gateways) that a Route wants to be attached to. | +| [2] | `name` | Name of the referent. | +| [3] | `namespace` | Namespace of the referent. When unspecified (or empty string), this refers to the local namespace of the Route. | +| [4] | `sectionName` | Name of a section within the target resource (the Listener name). | +| [5] | `hostnames` | Defines a set of SNI names that should match against the SNI attribute of TLS ClientHello message in TLS handshake. | +| [6] | `rules` | Rules are a list of TCP matchers and actions. | +| [7] | `backendRefs` | Defines the backend(s) where matching requests should be sent. | +| [8] | `name` | The name of the referent service. | +| [9] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). | +| [10] | `port` | The port of the referent service. | +| [11] | `group` | Group is the group of the referent. Only `traefik.containo.us` and `gateway.networking.k8s.io` values are supported. | +| [12] | `kind` | Kind is kind of the referent. Only `TraefikService` and `Service` values are supported. | diff --git a/go.mod b/go.mod index a4fe2756a..f4d03ab60 100644 --- a/go.mod +++ b/go.mod @@ -85,19 +85,19 @@ require ( golang.org/x/mod v0.4.2 golang.org/x/net v0.0.0-20210614182718-04defd469f4e golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 // indirect - golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 - golang.org/x/tools v0.1.2 + golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac + golang.org/x/tools v0.1.5 google.golang.org/grpc v1.38.0 gopkg.in/DataDog/dd-trace-go.v1 v1.19.0 gopkg.in/fsnotify.v1 v1.4.7 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b - k8s.io/api v0.21.0 - k8s.io/apiextensions-apiserver v0.20.2 - k8s.io/apimachinery v0.21.0 - k8s.io/client-go v0.21.0 - k8s.io/utils v0.0.0-20210709001253-0e1f9d693477 + k8s.io/api v0.22.1 + k8s.io/apiextensions-apiserver v0.21.3 + k8s.io/apimachinery v0.22.1 + k8s.io/client-go v0.22.1 + k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e mvdan.cc/xurls/v2 v2.1.0 - sigs.k8s.io/gateway-api v0.3.0 + sigs.k8s.io/gateway-api v0.4.0 ) // Containous forks diff --git a/go.sum b/go.sum index 52e005ad3..0ca5fbf9f 100644 --- a/go.sum +++ b/go.sum @@ -10,20 +10,35 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= @@ -40,16 +55,15 @@ github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSW github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= github.com/Azure/go-autorest/autorest v0.10.0/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= -github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= github.com/Azure/go-autorest/autorest v0.11.17/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= +github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= github.com/Azure/go-autorest/autorest v0.11.19 h1:7/IqD2fEYVha1EPeaiytVKhzmPV223pfkRIQUGOK2IE= github.com/Azure/go-autorest/autorest v0.11.19/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/adal v0.9.11/go.mod h1:nBKAnTomx8gDtl+3ZCJv2v0KACFHWTB2drffI1B68Pk= github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= @@ -67,7 +81,6 @@ github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSY github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= @@ -107,6 +120,7 @@ github.com/Microsoft/hcsshim v0.8.7 h1:ptnOoufxGSzauVTsdE+wMYnCWA301PdoN4xg5oRdZ github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 h1:xPMsUicZ3iosVPSIP7bW5EcGUzjiiMl1OYTe14y/R24= github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks= @@ -125,7 +139,7 @@ github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJM github.com/abronan/valkeyrie v0.2.0 h1:jkig3zG67iCRcglnUFZeH1f/J0alJFnIxY8102jSejE= github.com/abronan/valkeyrie v0.2.0/go.mod h1:U0C/aC7N9PzFdftYQuflxuuRGsK/48JeYiSzgWuehsQ= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/ahmetb/gen-crd-api-reference-docs v0.2.1-0.20201224172655-df869c1245d4/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8= +github.com/ahmetb/gen-crd-api-reference-docs v0.3.0/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8= github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.1 h1:bLzehmpyCwQiqCE1Qe9Ny6fbFqs7hPlmo9vKv2orUxs= github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.1/go.mod h1:kX6YddBkXqqywAe8c9LyvgTCyFuZCTMF4cRPQhc3Fy8= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -159,12 +173,15 @@ github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN github.com/aws/aws-sdk-go v1.39.0 h1:74BBwkEmiqBbi2CGflEh34l0YNtIibTjZsibGarkNjo= github.com/aws/aws-sdk-go v1.39.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= @@ -198,6 +215,7 @@ github.com/cloudflare/cloudflare-go v0.20.0 h1:y2a6KwYHTFxhw+8PLhz0q5hpTGj6Un3W1 github.com/cloudflare/cloudflare-go v0.20.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF1FhM7N60fuNiFdYTI= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200313221541-5f7e5dd04533/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= @@ -251,6 +269,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -321,23 +340,28 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.5/go.mod h1:OXl5to++W0ctG+EHWTFUjiypVxC/Y4VLc/KFU+al13s= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= +github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exoscale/egoscale v0.67.0 h1:qgWh7T5IZGrNWtg6ib4dr+76WThvB+odTtGG+DGbXF8= github.com/exoscale/egoscale v0.67.0/go.mod h1:wi0myUxPsV8SdEtdJHQJxFLL/wEw9fiw9Gs1PWRkvkM= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= +github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= @@ -373,10 +397,9 @@ github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/zapr v0.2.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU= +github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= @@ -385,12 +408,14 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34 github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48 h1:JVrqSeQfdhYRFk24TvhTZWU0q8lfCojxZQFi3Ou7+uY= github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -402,7 +427,7 @@ github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr6 github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b h1:/vQ+oYKu+JoyaMPDsv5FzwuL2wwWBgBbtj/YLCi4LuA= github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw= -github.com/gobuffalo/flect v0.2.2/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= +github.com/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= @@ -412,7 +437,6 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= @@ -421,15 +445,18 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -448,6 +475,7 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -456,17 +484,22 @@ github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo= @@ -482,11 +515,19 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2/go.mod h1:DavVbd41y+b7ukKDmlnPR4nGYmkWXR6vHUkjQNiHPBs= @@ -503,8 +544,9 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= +github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.15.1-0.20210202035223-633d73521055/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4= github.com/gophercloud/gophercloud v0.16.0 h1:sWjPfypuzxRxjVbk3/MsU4H8jS0NNlyauZtIUl78BPU= @@ -639,9 +681,9 @@ github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5 github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= @@ -672,6 +714,7 @@ github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8 github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f/go.mod h1:KDSfL7qe5ZfQqvlDMkVjCztbmcpp/c8M77vhQP8ZPvk= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -748,8 +791,9 @@ github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 h1:Kg/NPZLLC3aAFr1YToMs98dbCdhootQ1hZIvZU28hAQ= github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51/go.mod h1:RYmqHbhWwIz3z9eVmQ2rx82rulEMG0t+Q1bzfc9DYN4= github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f h1:ZZYhg16XocqSKPGNQAe0aeweNtFxuedbwwb4fSlg7h4= @@ -759,6 +803,7 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= @@ -828,7 +873,7 @@ github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -888,7 +933,6 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= @@ -898,7 +942,6 @@ github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/onsi/gomega v1.14.0 h1:ep6kpPVwmr/nTbklSx2nrLNSIO62DoYAhnPNIMhK8gI= github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= @@ -940,6 +983,7 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= @@ -1106,12 +1150,14 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -1123,6 +1169,7 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -1205,7 +1252,9 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.elastic.co/apm v1.13.1 h1:ICIcUcQOImg/bve9mQVyLCvm1cSUZ1afdwK6ACnxczU= @@ -1236,30 +1285,30 @@ go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277 h1:d9qaMM+ODpCq+9We41//fu/sHsTnXcrqd1en3x+GKy4= go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= -go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.18.1 h1:CSUJ2mjFszzEWt4CdKISEuChVIXGBn3lAPwkRGyVrc4= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1328,6 +1377,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1365,20 +1416,28 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1387,8 +1446,15 @@ golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAG golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1396,6 +1462,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= @@ -1456,28 +1524,43 @@ golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo= golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1502,8 +1585,9 @@ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 h1:Vv0JUPWTyeqUq42B2WJ1FeIDjjvGKoA2Ss+Ts0lAVbs= golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1547,24 +1631,39 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= +gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= @@ -1578,8 +1677,20 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0 h1:jz2KixHX7EcCPiQrySzPdnYT7DbINAypCqKZ1Z7GM40= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0 h1:URs6qR1lAxDsqWITsQXI4ZkGiYJ5dHtRNiCpfs2OeKA= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1588,8 +1699,9 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -1612,10 +1724,31 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -1634,7 +1767,17 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1713,6 +1856,7 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1721,36 +1865,29 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M= howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= k8s.io/api v0.16.9/go.mod h1:Y7dZNHs1Xy0mSwSlzL9QShi6qkljnN41yR8oWCRTDe8= -k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= -k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8= -k8s.io/api v0.21.0 h1:gu5iGF4V6tfVCQ/R+8Hc0h7H1JuEhzyEi9S4R5LM8+Y= -k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= -k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk= -k8s.io/apiextensions-apiserver v0.20.2 h1:rfrMWQ87lhd8EzQWRnbQ4gXrniL/yTRBgYH1x1+BLlo= -k8s.io/apiextensions-apiserver v0.20.2/go.mod h1:F6TXp389Xntt+LUq3vw6HFOLttPa0V8821ogLGwb6Zs= +k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg= +k8s.io/api v0.22.1 h1:ISu3tD/jRhYfSW8jI/Q1e+lRxkR7w9UwQEZ7FgslrwY= +k8s.io/api v0.22.1/go.mod h1:bh13rkTp3F1XEaLGykbyRD2QaTTzPm0e/BMd8ptFONY= +k8s.io/apiextensions-apiserver v0.21.3 h1:+B6biyUWpqt41kz5x6peIsljlsuwvNAp/oFax/j2/aY= +k8s.io/apiextensions-apiserver v0.21.3/go.mod h1:kl6dap3Gd45+21Jnh6utCx8Z2xxLm8LGDkprcd+KbsE= k8s.io/apimachinery v0.16.9/go.mod h1:Xk2vD2TRRpuWYLQNM6lT9R7DSFZUYG03SarNkbGrnKE= -k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.21.0 h1:3Fx+41if+IRavNcKOz09FwEXDBG6ORh6iMsTSelhkMA= -k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= -k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/apiserver v0.20.2/go.mod h1:2nKd93WyMhZx4Hp3RfgH2K5PhwyTrprrkWYnI7id7jA= +k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI= +k8s.io/apimachinery v0.22.1 h1:DTARnyzmdHMz7bFWFDDm22AM4pLWTQECMpRTFu2d2OM= +k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= +k8s.io/apiserver v0.21.3/go.mod h1:eDPWlZG6/cCCMj/JBcEpDoK+I+6i3r9GsChYBHSbAzU= k8s.io/client-go v0.16.9/go.mod h1:ThjPlh7Kx+XoBFOCt775vx5J7atwY7F/zaFzTco5gL0= -k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= -k8s.io/client-go v0.20.2/go.mod h1:kH5brqWqp7HDxUFKoEgiI4v8G1xzbe9giaCenUWJzgE= -k8s.io/client-go v0.21.0 h1:n0zzzJsAQmJngpC0IhgFcApZyoGXPrDIAD601HD09ag= -k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA= -k8s.io/code-generator v0.20.1/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg= -k8s.io/code-generator v0.20.2/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg= -k8s.io/code-generator v0.21.0/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q= -k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= -k8s.io/component-base v0.20.2/go.mod h1:pzFtCiwe/ASD0iV7ySMu8SYVJjCapNM9bjvk7ptpKh0= +k8s.io/client-go v0.21.3/go.mod h1:+VPhCgTsaFmGILxR/7E1N0S+ryO010QBeNCv5JwRGYU= +k8s.io/client-go v0.22.1 h1:jW0ZSHi8wW260FvcXHkIa0NLxFBQszTlhiAVsU5mopw= +k8s.io/client-go v0.22.1/go.mod h1:BquC5A4UOo4qVDUtoc04/+Nxp1MeHcVc1HJm1KmG8kk= +k8s.io/code-generator v0.21.3/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo= +k8s.io/code-generator v0.22.0/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= +k8s.io/component-base v0.21.3/go.mod h1:kkuhtfEHeZM6LkX0saqSK8PbdO7A0HigUngmhhrwfGQ= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= @@ -1760,36 +1897,37 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.8.0 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts= k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/klog/v2 v2.10.0 h1:R2HDMDJsHVTHA2n4RjwbeYXdOcBymXdX/JRb1v0VGhE= +k8s.io/klog/v2 v2.10.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 h1:vEx13qjvaZ4yfObSSXW7BrMc/KQBBT/Jyee8XtLf4x0= k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= +k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM= +k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210305010621-2afb4311ab10/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210709001253-0e1f9d693477 h1:AuP1OP6ExD2U8pP9w85xHtmgBn/Ob3pngZwWMe12GBQ= -k8s.io/utils v0.0.0-20210709001253-0e1f9d693477/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210722164352-7f3ee0f31471/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e h1:ldQh+neBabomh7+89dTpiFAB8tGdfVmuIzAHbvtl+9I= +k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= mvdan.cc/xurls/v2 v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA= mvdan.cc/xurls/v2 v2.1.0/go.mod h1:5GrSd9rOnKOpZaji1OZLYL/yeAAtGDlo/cFe+8K5n8E= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/controller-runtime v0.8.3/go.mod h1:U/l+DUopBc1ecfRZ5aviA9JDmGFQKvLf5YkZNx2e0sU= -sigs.k8s.io/controller-tools v0.5.0/go.mod h1:JTsstrMpxs+9BUj6eGuAaEb6SDSPTeVtUyp0jmnAM/I= -sigs.k8s.io/gateway-api v0.3.0 h1:mKbQRlRIIY3dsCCbNF9Jv30V9vvOf6SRG82l0MfJQ9U= -sigs.k8s.io/gateway-api v0.3.0/go.mod h1:Wb8bx7QhGVZxOSEU3i9vw/JqTB5Nlai9MLMYVZeDmRQ= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/controller-runtime v0.9.6/go.mod h1:q6PpkM5vqQubEKUKOM6qr06oXGzOBcCby1DA9FbyZeA= +sigs.k8s.io/controller-tools v0.6.2/go.mod h1:oaeGpjXn6+ZSEIQkUe/+3I40PNiDYp9aeawbt3xTgJ8= +sigs.k8s.io/gateway-api v0.4.0 h1:07IJkTt21NetZTHtPKJk2I4XIgDN4BAlTIq1wK7V11o= +sigs.k8s.io/gateway-api v0.4.0/go.mod h1:r3eiNP+0el+NTLwaTfOrCNXy8TukC+dIM3ggc+fbNWk= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.0 h1:C4r9BgJ98vrKnnVCjwCSXcWjWe0NKcUQkmzDXZXGwH8= -sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/integration/fixtures/k8s/01-gateway-api-crd.yml b/integration/fixtures/k8s/01-gateway-api-crd.yml new file mode 100644 index 000000000..cb10d17d5 --- /dev/null +++ b/integration/fixtures/k8s/01-gateway-api-crd.yml @@ -0,0 +1,3140 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + creationTimestamp: null + name: gatewayclasses.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: GatewayClass + listKind: GatewayClassList + plural: gatewayclasses + shortNames: + - gc + singular: gatewayclass + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.controller + name: Controller + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.description + name: Description + priority: 1 + type: string + name: v1alpha2 + schema: + openAPIV3Schema: + description: "GatewayClass describes a class of Gateways available to the + user for creating Gateway resources. \n It is recommended that this resource + be used as a template for Gateways. This means that a Gateway is based on + the state of the GatewayClass at the time it was created and changes to + the GatewayClass or associated parameters are not propagated down to existing + Gateways. This recommendation is intended to limit the blast radius of changes + to GatewayClass or associated parameters. If implementations choose to propagate + GatewayClass changes to existing Gateways, that MUST be clearly documented + by the implementation. \n Whenever one or more Gateways are using a GatewayClass, + implementations MUST add the `gateway-exists-finalizer.gateway.networking.k8s.io` + finalizer on the associated GatewayClass. This ensures that a GatewayClass + associated with a Gateway is not deleted while in use. \n GatewayClass is + a Cluster level resource." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GatewayClass. + properties: + controllerName: + description: "ControllerName is the name of the controller that is + managing Gateways of this class. The value of this field MUST be + a domain prefixed path. \n Example: \"example.net/gateway-controller\". + \n This field is not mutable and cannot be empty. \n 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])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + description: + description: Description helps describe a GatewayClass with more details. + maxLength: 64 + type: string + parametersRef: + description: "ParametersRef is a reference to a resource that contains + the configuration parameters corresponding to the GatewayClass. + This is optional if the controller does not require any additional + configuration. \n ParametersRef can reference a standard Kubernetes + resource, i.e. ConfigMap, or an implementation-specific custom resource. + The resource can be cluster-scoped or namespace-scoped. \n If the + referent cannot be found, the GatewayClass's \"InvalidParameters\" + status condition will be true. \n Support: Custom" + properties: + group: + description: Group is the group of the referent. + 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. + 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 referent. This + field is required when referring to a Namespace-scoped resource + and MUST be unset when referring to a Cluster-scoped resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + required: + - controllerName + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Waiting + status: Unknown + type: Accepted + description: Status defines the current state of GatewayClass. + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Waiting + status: Unknown + type: Accepted + description: "Conditions is the current status from the controller + for this GatewayClass. \n Controllers should prefer to publish conditions + using values of GatewayClassConditionType for the type of each Condition." + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + creationTimestamp: null + name: gateways.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: Gateway + listKind: GatewayList + plural: gateways + shortNames: + - gtw + singular: gateway + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.gatewayClassName + name: Class + type: string + - jsonPath: .status.addresses[*].value + name: Address + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: Gateway represents an instance of a service-traffic handling + infrastructure by binding Listeners to a set of IP addresses. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of Gateway. + properties: + addresses: + description: "Addresses requested for this Gateway. This is optional + and behavior can depend on the implementation. If a value is set + in the spec and the requested address is invalid or unavailable, + the implementation MUST indicate this in the associated entry in + GatewayStatus.Addresses. \n The Addresses field represents a request + for the address(es) on the \"outside of the Gateway\", that traffic + bound for this Gateway will use. This could be the IP address or + hostname of an external load balancer or other networking infrastructure, + or some other address that traffic will be sent to. \n The .listener.hostname + field is used to route traffic that has already arrived at the Gateway + to the correct in-cluster destination. \n If no Addresses are specified, + the implementation MAY schedule the Gateway in an implementation-specific + manner, assigning an appropriate set of Addresses. \n The implementation + MUST bind all Listeners to every GatewayAddress that it assigns + to the Gateway and add a corresponding entry in GatewayStatus.Addresses. + \n Support: Core" + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + properties: + type: + default: IPAddress + description: Type of the address. + enum: + - IPAddress + - Hostname + - NamedAddress + type: string + value: + description: "Value of the address. The validity of the values + will depend on the type and support by the controller. \n + Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + maxItems: 16 + type: array + gatewayClassName: + description: GatewayClassName used for this Gateway. This is the name + of a GatewayClass resource. + maxLength: 253 + minLength: 1 + type: string + listeners: + description: "Listeners associated with this Gateway. Listeners define + logical endpoints that are bound on this Gateway's addresses. At + least one Listener MUST be specified. \n Each listener in a Gateway + must have a unique combination of Hostname, Port, and Protocol. + \n An implementation MAY group Listeners by Port and then collapse + each group of Listeners into a single Listener if the implementation + determines that the Listeners in the group are \"compatible\". An + implementation MAY also group together and collapse compatible Listeners + belonging to different Gateways. \n For example, an implementation + might consider Listeners to be compatible with each other if all + of the following conditions are met: \n 1. Either each Listener + within the group specifies the \"HTTP\" Protocol or each Listener + within the group specifies either the \"HTTPS\" or \"TLS\" Protocol. + \n 2. Each Listener within the group specifies a Hostname that is + unique within the group. \n 3. As a special case, one Listener + within a group may omit Hostname, in which case this Listener + matches when no other Listener matches. \n If the implementation + does collapse compatible Listeners, the hostname provided in the + incoming client request MUST be matched to a Listener to find the + correct set of Routes. The incoming hostname MUST be matched using + the Hostname field for each Listener in order of most to least specific. + That is, exact matches must be processed before wildcard matches. + \n If this field specifies multiple Listeners that have the same + Port value but are not compatible, the implementation must raise + a \"Conflicted\" condition in the Listener status. \n Support: Core" + items: + description: Listener embodies the concept of a logical endpoint + where a Gateway accepts network connections. + properties: + allowedRoutes: + default: + namespaces: + from: Same + description: "AllowedRoutes defines the types of routes that + MAY be attached to a Listener and the trusted namespaces where + those Route resources MAY be present. \n Although a client + request may match multiple route rules, only one rule may + ultimately receive the request. Matching precedence MUST be + determined in order of the following criteria: \n * The most + specific match as defined by the Route type. * The oldest + Route based on creation timestamp. For example, a Route with + \ a creation timestamp of \"2020-09-08 01:02:03\" is given + precedence over a Route with a creation timestamp of \"2020-09-08 + 01:02:04\". * If everything else is equivalent, the Route + appearing first in alphabetical order (namespace/name) should + be given precedence. For example, foo/bar is given precedence + over foo/baz. \n All valid rules within a Route attached to + this Listener should be implemented. Invalid Route rules can + be ignored (sometimes that will mean the full Route). If a + Route rule transitions from valid to invalid, support for + that Route rule should be dropped to ensure consistency. For + example, even if a filter specified by a Route rule is invalid, + the rest of the rules within that Route should still be supported. + \n Support: Core" + properties: + kinds: + description: "Kinds specifies the groups and kinds of Routes + that are allowed to bind to this Gateway Listener. When + unspecified or empty, the kinds of Routes selected are + determined using the Listener protocol. \n A RouteGroupKind + MUST correspond to kinds of Routes that are compatible + with the application protocol specified in the Listener's + Protocol field. If an implementation does not support + or recognize this resource type, it MUST set the \"ResolvedRefs\" + condition to False for this Listener with the \"InvalidRoutesRef\" + reason. \n Support: Core" + items: + description: RouteGroupKind indicates the group and kind + of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + 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 the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + namespaces: + default: + from: Same + description: "Namespaces indicates namespaces from which + Routes may be attached to this Listener. This is restricted + to the namespace of this Gateway by default. \n Support: + Core" + properties: + from: + default: Same + description: "From indicates where Routes will be selected + for this Gateway. Possible values are: * All: Routes + in all namespaces may be used by this Gateway. * Selector: + Routes in namespaces selected by the selector may + be used by this Gateway. * Same: Only Routes in + the same namespace may be used by this Gateway. \n + Support: Core" + enum: + - All + - Selector + - Same + type: string + selector: + description: "Selector must be specified when From is + set to \"Selector\". In that case, only Routes in + Namespaces matching this Selector will be selected + by this Gateway. This field is ignored for other values + of \"From\". \n Support: Core" + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + type: object + type: object + hostname: + description: "Hostname specifies the virtual hostname to match + for protocol types that define this concept. When unspecified, + all hostnames are matched. This field is ignored for protocols + that don't require hostname based matching. \n Implementations + MUST apply Hostname matching appropriately for each of the + following protocols: \n * TLS: The Listener Hostname MUST + match the SNI. * HTTP: The Listener Hostname MUST match the + Host header of the request. * HTTPS: The Listener Hostname + SHOULD match at both the TLS and HTTP protocol layers as + described above. If an implementation does not ensure that + both the SNI and Host header match the Listener hostname, + \ it MUST clearly document that. \n For HTTPRoute and TLSRoute + resources, there is an interaction with the `spec.hostnames` + array. When both listener and route specify hostnames, there + MUST be an intersection between the values for a Route to + be accepted. For more information, refer to the Route specific + Hostnames documentation. \n 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 + name: + description: "Name is the name of the Listener. \n 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 + port: + description: "Port is the network port. Multiple listeners may + use the same port, subject to the Listener compatibility rules. + \n Support: Core" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: "Protocol specifies the network protocol this listener + expects to receive. \n Support: Core" + maxLength: 255 + minLength: 1 + pattern: ^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ + type: string + tls: + description: "TLS is the TLS configuration for the Listener. + This field is required if the Protocol field is \"HTTPS\" + or \"TLS\". It is invalid to set this field if the Protocol + field is \"HTTP\", \"TCP\", or \"UDP\". \n The association + of SNIs to Certificate defined in GatewayTLSConfig is defined + based on the Hostname field for this listener. \n The GatewayClass + MUST use the longest matching SNI out of all available certificates + for any TLS handshake. \n Support: Core" + properties: + certificateRefs: + description: "CertificateRefs contains a series of references + to Kubernetes objects that contains TLS certificates and + private keys. These certificates are used to establish + a TLS handshake for requests that match the hostname of + the associated listener. \n A single CertificateRef to + a Kubernetes Secret has \"Core\" support. Implementations + MAY choose to support attaching multiple certificates + to a Listener, but this behavior is implementation-specific. + \n References to a resource in different namespace are + invalid UNLESS there is a ReferencePolicy in the target + namespace that allows the certificate to be attached. + If a ReferencePolicy does not allow this reference, the + \"ResolvedRefs\" condition MUST be set to False for this + listener with the \"InvalidCertificateRef\" reason. \n + This field is required to have at least one element when + the mode is set to \"Terminate\" (default) and is optional + otherwise. \n CertificateRefs can reference to standard + Kubernetes resources, i.e. Secret, or implementation-specific + custom resources. \n Support: Core - A single reference + to a Kubernetes Secret \n Support: Implementation-specific + (More than one reference or other resource types)" + items: + description: "SecretObjectReference identifies an API + object including its namespace, defaulting to Secret. + \n The API object must be valid in the cluster; the + Group and Kind must be registered in the cluster for + this reference to be valid. \n References to objects + with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate + Conditions set on the containing object." + properties: + group: + default: "" + description: Group is the group of the referent. For + example, "networking.k8s.io". When unspecified (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: Secret + 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 + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. + \n Note that when a namespace is specified, a ReferencePolicy + object is required in the referent namespace to + allow that namespace's owner to accept the reference. + See the ReferencePolicy documentation for details. + \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + maxItems: 64 + type: array + mode: + default: Terminate + description: "Mode defines the TLS behavior for the TLS + session initiated by the client. There are two possible + modes: \n - Terminate: The TLS session between the downstream + client and the Gateway is terminated at the Gateway. + This mode requires certificateRefs to be set and contain + at least one element. - Passthrough: The TLS session is + NOT terminated by the Gateway. This implies that the + Gateway can't decipher the TLS stream except for the + ClientHello message of the TLS protocol. CertificateRefs + field is ignored in this mode. \n Support: Core" + enum: + - Terminate + - Passthrough + type: string + options: + additionalProperties: + description: AnnotationValue is the value of an annotation + in Gateway API. This is used for validation of maps + such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation + in that case is based on the entire size of the annotations + struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Options are a list of key/value pairs to enable + extended TLS configuration for each implementation. For + example, configuring the minimum TLS version or supported + cipher suites. \n A set of common keys MAY be defined + by the API in the future. To avoid any ambiguity, implementation-specific + definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. + Un-prefixed names are reserved for key names defined by + Gateway API. \n Support: Implementation-specific" + maxProperties: 16 + type: object + type: object + required: + - name + - port + - protocol + type: object + maxItems: 64 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + required: + - gatewayClassName + - listeners + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: NotReconciled + status: Unknown + type: Scheduled + description: Status defines the current state of Gateway. + properties: + addresses: + description: Addresses lists the IP addresses that have actually been + bound to the Gateway. These addresses may differ from the addresses + in the Spec, e.g. if the Gateway automatically assigns an address + from a reserved pool. + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + properties: + type: + default: IPAddress + description: Type of the address. + enum: + - IPAddress + - Hostname + - NamedAddress + type: string + value: + description: "Value of the address. The validity of the values + will depend on the type and support by the controller. \n + Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + maxItems: 16 + type: array + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: NotReconciled + status: Unknown + type: Scheduled + description: "Conditions describe the current conditions of the Gateway. + \n Implementations should prefer to express Gateway conditions using + the `GatewayConditionType` and `GatewayConditionReason` constants + so that operators and tools can converge on a common vocabulary + to describe Gateway state. \n Known condition types are: \n * \"Scheduled\" + * \"Ready\"" + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + listeners: + description: Listeners provide status for each unique listener port + defined in the Spec. + items: + description: ListenerStatus is the status associated with a Listener. + properties: + attachedRoutes: + description: AttachedRoutes represents the total number of Routes + that have been successfully attached to this Listener. + format: int32 + type: integer + conditions: + description: Conditions describe the current condition of this + listener. + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + name: + description: Name is the name of the Listener that this status + corresponds to. + 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 + supportedKinds: + description: "SupportedKinds is the list indicating the Kinds + supported by this listener. This MUST represent the kinds + an implementation supports for that Listener configuration. + \n If kinds are specified in Spec that are not supported, + they MUST NOT appear in this list and an implementation MUST + set the \"ResolvedRefs\" condition to \"False\" with the \"InvalidRouteKinds\" + reason. If both valid and invalid Route kinds are specified, + the implementation MUST reference the valid Route kinds that + have been specified." + items: + description: RouteGroupKind indicates the group and kind of + a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + 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 the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + required: + - attachedRoutes + - conditions + - name + - supportedKinds + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + creationTimestamp: null + name: httproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: HTTPRoute + listKind: HTTPRouteList + plural: httproutes + singular: httproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: HTTPRoute provides a way to route HTTP requests. This includes + the capability to match requests by hostname, path, header, or query param. + Filters can be used to specify additional processing steps. Backends specify + where matching requests should be routed. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of HTTPRoute. + properties: + hostnames: + description: "Hostnames defines a set of hostname that should match + against the HTTP Host header to select a HTTPRoute to process the + request. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may + be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n If a hostname is specified + by both the Listener and HTTPRoute, there must be at least one intersecting + hostname for the HTTPRoute to be attached to the Listener. For example: + \n * A Listener with `test.example.com` as the hostname matches + HTTPRoutes that have either not specified any hostnames, or have + specified at least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches HTTPRoutes + \ that have either not specified any hostnames or have specified + at least one hostname that matches the Listener hostname. For + example, `test.example.com` and `*.example.com` would both match. + On the other hand, `example.com` and `test.example.net` would + not match. \n If both the Listener and HTTPRoute have specified + hostnames, any HTTPRoute hostnames that do not match the Listener + hostname MUST be ignored. For example, if a Listener specified `*.example.com`, + and the HTTPRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. \n If both + the Listener and HTTPRoute have specified hostnames, and none match + with the criteria above, then the HTTPRoute is not accepted. The + implementation must raise an 'Accepted' Condition with a status + of `False` in the corresponding RouteParentStatus. \n Support: Core" + items: + description: "Hostname is the fully qualified domain name of a network + host. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname + may be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n Hostname can be \"precise\" + which is a domain name without the terminating dot of a network + host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain + name prefixed with a single wildcard label (e.g. `*.example.com`). + \n Note that as per RFC1035 and RFC1123, a *label* must consist + of lower case alphanumeric characters or '-', and must start and + end with an alphanumeric character. No other punctuation is allowed." + 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 + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) + that a Route wants to be attached to. Note that the referenced parent + resource needs to allow this for the attachment to be complete. + For Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. \n The only kind of parent resource + with \"Core\" support is Gateway. This API may be extended in the + future to support additional kinds of parent resources such as one + of the route kinds. \n It is invalid to reference an identical parent + more than once. It is valid to reference multiple distinct sections + within the same parent resource, such as 2 Listeners within a Gateway. + \n It is possible to separately reference multiple distinct objects + that may be collapsed by an implementation. For example, some implementations + may choose to merge compatible Gateway Listeners together. If that + is the case, the list of routes attached to those resources should + also be merged." + items: + description: "ParentRef identifies an API object (usually a Gateway) + that can be considered a parent of this resource (usually a route). + The only kind of parent resource with \"Core\" support is Gateway. + This API may be extended in the future to support additional kinds + of parent resources, such as HTTPRoute. \n The API object must + be valid in the cluster; the Group and Kind must be registered + in the cluster for this reference to be valid. \n References to + objects with invalid Group and Kind are not valid, and must be + rejected by the implementation, with appropriate Conditions set + on the containing object." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + 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: Gateway + description: "Kind is kind of the referent. \n Support: Core + (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified (or empty string), this refers to the local namespace + of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name + \n Implementations MAY choose to support attaching Routes + to other resources. If that is the case, they MUST clearly + document how SectionName is interpreted. \n When unspecified + (empty string), this will reference the entire resource. For + the purpose of status, an attachment is considered successful + if at least one section in the parent resource accepts it. + For example, Gateway listeners can restrict which Routes can + attach to them by Route kind, namespace, or hostname. If 1 + of 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. \n + 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 + required: + - name + type: object + maxItems: 32 + type: array + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + description: Rules are a list of HTTP matchers, filters and actions. + items: + description: HTTPRouteRule defines semantics for matching an HTTP + request based on conditions (matches), processing it (filters), + and forwarding the request to an API object (backendRefs). + properties: + backendRefs: + description: "If unspecified or invalid (refers to a non-existent + resource or a Service with no endpoints), the rule performs + no forwarding. If there are also no filters specified that + would result in a response being sent, a HTTP 503 status code + is returned. 503 responses must be sent so that the overall + weight is respected; if an invalid backend is requested to + have 80% of requests, then 80% of requests must get a 503 + instead. \n Support: Core for Kubernetes Service Support: + Custom for any other resource \n Support for weight: Core" + items: + description: HTTPBackendRef defines how a HTTPRoute should + forward an HTTP request. + properties: + filters: + description: "Filters defined at this level should be + executed if and only if the request is being forwarded + to the backend defined here. \n Support: Custom (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. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. + For example, "networking.k8s.io". When unspecified + (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 + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema + for a filter that modifies request headers. \n + 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. \n Input: GET /foo + HTTP/1.1 my-header: foo \n Config: add: + \ - name: \"my-header\" value: \"bar\" + \n Output: GET /foo HTTP/1.1 my-header: + foo 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). + \n 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 + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - 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). + \n Input: GET /foo HTTP/1.1 my-header1: + foo my-header2: bar my-header3: baz \n + Config: remove: [\"my-header1\", \"my-header3\"] + \n Output: GET /foo HTTP/1.1 my-header2: + bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with + the given header (name, value) before the + action. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: set: - name: \"my-header\" + \ value: \"bar\" \n 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). + \n 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 + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + 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. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource + where mirrored requests are sent. \n 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. \n If there is + a cross-namespace reference to an *existing* + object that is not allowed by a ReferencePolicy, + 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. \n In either error case, the + Message of the `ResolvedRefs` Condition should + be used to provide more detail about the problem. + \n Support: Extended for Kubernetes Service + Support: Custom for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "networking.k8s.io". When + unspecified (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 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 + namespace: + description: "Namespace is the namespace + of the backend. When unspecified, the + local namespace is inferred. \n Note that + when a namespace is specified, a ReferencePolicy + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferencePolicy + documentation for details. \n 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. For other resources, + destination port might be derived from + the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for + a filter that responds to the request with an + HTTP redirection. \n 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 + of the request is used. \n 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 + port: + description: "Port is the port to be used in + the value of the `Location` header in the + response. When empty, port (if specified) + of the request is used. \n 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. \n Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status + code to be used in response. \n Support: Core" + enum: + - 301 + - 302 + type: integer + type: object + type: + description: "Type identifies the type of filter + to apply. As with other API fields, types are + classified into three conformance levels: \n - + Core: Filter types and their corresponding configuration + defined by \"Support: Core\" in this package, + e.g. \"RequestHeaderModifier\". All implementations + must support core filters. \n - Extended: Filter + types and their corresponding configuration defined + by \"Support: Extended\" in this package, e.g. + \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Custom: 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. \n Implementers are encouraged + to define custom implementation types to extend + the core API with implementation-specific behavior. + \n 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." + enum: + - RequestHeaderModifier + - RequestMirror + - RequestRedirect + - ExtensionRef + type: string + required: + - type + type: object + maxItems: 16 + type: array + group: + default: "" + description: Group is the group of the referent. For example, + "networking.k8s.io". When unspecified (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 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 + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace is specified, a ReferencePolicy + object is required in the referent namespace to allow + that namespace's owner to accept the reference. See + the ReferencePolicy documentation for details. \n 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. For other resources, + destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests + forwarded to the referenced backend. This is computed + as weight/(sum of all weights in this BackendRefs list). + For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision + an implementation supports. Weight is not a percentage + and the sum of weights does not need to equal 100. \n + If only one backend is specified and it has a weight + greater than 0, 100% of the traffic is forwarded to + that backend. If weight is set to 0, no traffic should + be forwarded for this entry. If unspecified, weight + defaults to 1. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + maxItems: 16 + type: array + filters: + description: "Filters define the filters that are applied to + requests that match this rule. \n The effects of ordering + of multiple behaviors are currently unspecified. This can + change in the future based on feedback during the alpha stage. + \n Conformance-levels at this level are defined based on the + type of filter: \n - ALL core filters MUST be supported by + all implementations. - Implementers are encouraged to support + extended filters. - Implementation-specific custom filters + have no API guarantees across implementations. \n Specifying + a core filter multiple times has unspecified or custom conformance. + \n Support: Core" + 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. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. For + example, "networking.k8s.io". When unspecified (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 + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for + a filter that modifies request headers. \n 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. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: add: - name: \"my-header\" value: + \"bar\" \n Output: GET /foo HTTP/1.1 my-header: + foo 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). + \n 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 + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - 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). + \n Input: GET /foo HTTP/1.1 my-header1: foo + \ my-header2: bar my-header3: baz \n Config: + \ remove: [\"my-header1\", \"my-header3\"] \n Output: + \ GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with the + given header (name, value) before the action. \n + Input: GET /foo HTTP/1.1 my-header: foo \n Config: + \ set: - name: \"my-header\" value: \"bar\" + \n 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). + \n 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 + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + 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. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where + mirrored requests are sent. \n 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. \n If + there is a cross-namespace reference to an *existing* + object that is not allowed by a ReferencePolicy, + 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. \n + In either error case, the Message of the `ResolvedRefs` + Condition should be used to provide more detail + about the problem. \n Support: Extended for Kubernetes + Service Support: Custom for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "networking.k8s.io". When unspecified + (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 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 + namespace: + description: "Namespace is the namespace of the + backend. When unspecified, the local namespace + is inferred. \n Note that when a namespace is + specified, a ReferencePolicy object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferencePolicy + documentation for details. \n 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. For + other resources, destination port might be derived + from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for a filter + that responds to the request with an HTTP redirection. + \n 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 of the request is used. + \n 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 + port: + description: "Port is the port to be used in the value + of the `Location` header in the response. When empty, + port (if specified) of the request is used. \n 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. \n + Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status code to + be used in response. \n Support: Core" + enum: + - 301 + - 302 + type: integer + type: object + type: + description: "Type identifies the type of filter to apply. + As with other API fields, types are classified into + three conformance levels: \n - Core: Filter types and + their corresponding configuration defined by \"Support: + Core\" in this package, e.g. \"RequestHeaderModifier\". + All implementations must support core filters. \n + - Extended: Filter types and their corresponding configuration + defined by \"Support: Extended\" in this package, + e.g. \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Custom: 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. \n + Implementers are encouraged to define custom implementation + types to extend the core API with implementation-specific + behavior. \n 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." + enum: + - RequestHeaderModifier + - RequestMirror + - RequestRedirect + - ExtensionRef + type: string + required: + - type + type: object + maxItems: 16 + type: array + matches: + default: + - path: + type: PathPrefix + value: / + description: "Matches define conditions used for matching the + rule against incoming HTTP requests. Each match is independent, + i.e. this rule will be matched if **any** one of the matches + is satisfied. \n For example, take the following matches configuration: + \n ``` matches: - path: value: \"/foo\" headers: - + name: \"version\" value: \"v2\" - path: value: \"/v2/foo\" + ``` \n For a request to match against this rule, a request + must satisfy EITHER of the two conditions: \n - path prefixed + with `/foo` AND contains the header `version: v2` - path prefix + of `/v2/foo` \n See the documentation for HTTPRouteMatch on + how to specify multiple match conditions that should be ANDed + together. \n If no matches are specified, the default is a + prefix path match on \"/\", which has the effect of matching + every HTTP request. \n Proxy or Load Balancer routing configuration + generated from HTTPRoutes MUST prioritize rules based on the + following criteria, continuing on ties. Precedence must be + given to the the Rule with the largest number of: \n * Characters + in a matching non-wildcard hostname. * Characters in a matching + hostname. * Characters in a matching path. * Header matches. + * Query param matches. \n If ties still exist across multiple + Routes, matching precedence MUST be determined in order of + the following criteria, continuing on ties: \n * The oldest + Route based on creation timestamp. * The Route appearing first + in alphabetical order by \"/\". \n If ties + still exist within the Route that has been given precedence, + matching precedence MUST be granted to the first matching + rule meeting the above criteria." + items: + description: "HTTPRouteMatch defines the predicate used to + match requests to a given action. Multiple match types are + ANDed together, i.e. the match will evaluate to true only + if all conditions are satisfied. \n For example, the match + below will match a HTTP request only if its path starts + with `/foo` AND it contains the `version: v1` header: \n + ``` match: path: value: \"/foo\" headers: - name: + \"version\" value \"v1\" ```" + properties: + headers: + description: Headers specifies HTTP request header matchers. + Multiple match values are ANDed together, meaning, a + request must match all the specified headers to select + the route. + items: + description: HTTPHeaderMatch describes how to select + a HTTP route by matching HTTP request headers. + 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). + \n If multiple entries specify equivalent header + names, only 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. + \n When a header is repeated in an HTTP request, + it is implementation-specific behavior as to how + this is represented. Generally, proxies should + follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 + regarding processing a repeated header, with special + handling for \"Set-Cookie\"." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: "Type specifies how to match against + the value of the header. \n Support: Core (Exact) + \n Support: Custom (RegularExpression) \n Since + RegularExpression HeaderMatchType has custom conformance, + implementations can support POSIX, PCRE or any + other dialects of regular expressions. Please + read the implementation's documentation to determine + the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to + be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: "Method specifies HTTP method matcher. When + specified, this route will be matched only if the request + has the specified method. \n Support: Extended" + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + description: Path specifies a HTTP request path matcher. + If this field is not specified, a default prefix match + on the "/" path is provided. + properties: + type: + default: PathPrefix + description: "Type specifies how to match against + the path Value. \n Support: Core (Exact, PathPrefix) + \n Support: Custom (RegularExpression)" + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + queryParams: + description: QueryParams specifies HTTP query parameter + matchers. Multiple match values are ANDed together, + meaning, a request must match all the specified query + parameters to select the route. + items: + description: HTTPQueryParamMatch describes how to select + a HTTP route by matching HTTP query parameters. + properties: + name: + description: Name is the name of the HTTP query + param to be matched. This must be an exact string + match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). + maxLength: 256 + minLength: 1 + type: string + type: + default: Exact + description: "Type specifies how to match against + the value of the query parameter. \n Support: + Extended (Exact) \n Support: Custom (RegularExpression) + \n Since RegularExpression QueryParamMatchType + has custom conformance, implementations can support + POSIX, PCRE or any other dialects of regular expressions. + Please read the implementation's documentation + to determine the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param + to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + type: object + maxItems: 16 + type: array + type: object + status: + description: Status defines the current state of HTTPRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) + that are associated with the route, and the status of the route + with respect to each parent. When this route attaches to a parent, + the controller that manages the parent must add an entry to this + list when the controller first sees the route and should update + the entry as appropriate when the route or gateway is modified. + \n Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this + API can only populate Route status for the Gateways/parent resources + they are responsible for. \n A maximum of 32 Gateways will be represented + in this list. An empty list means the route has not been attached + to any Gateway." + items: + description: RouteParentStatus describes the status of a route with + respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with + respect to the Gateway. Note that the route's availability + is also subject to the Gateway's own status conditions and + listener status. \n If the Route's ParentRef specifies an + existing Gateway that supports Routes of this kind AND that + Gateway's controller has sufficient access, then that Gateway's + controller MUST set the \"Accepted\" condition on the Route, + to indicate whether the route has been accepted or rejected + by the Gateway, and why. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec + that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + 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: Gateway + description: "Kind is kind of the referent. \n Support: + Core (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified (or empty string), this refers to the + local namespace of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name \n Implementations MAY choose to support attaching + Routes to other resources. If that is the case, they MUST + clearly document how SectionName is interpreted. \n When + unspecified (empty string), this will reference the entire + resource. For the purpose of status, an attachment is + considered successful if at least one section in the parent + resource accepts it. For example, Gateway listeners can + restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept + attachment from the referencing Route, the Route MUST + be considered successfully attached. If no Gateway listeners + accept attachment from this Route, the Route MUST be considered + detached from the Gateway. \n 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 + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + creationTimestamp: null + name: tcproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: TCPRoute + listKind: TCPRouteList + plural: tcproutes + singular: tcproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: TCPRoute provides a way to route TCP requests. When combined + with a Gateway listener, it can be used to forward connections on the port + specified by the listener to a set of backends specified by the TCPRoute. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of TCPRoute. + properties: + parentRefs: + description: "ParentRefs references the resources (usually Gateways) + that a Route wants to be attached to. Note that the referenced parent + resource needs to allow this for the attachment to be complete. + For Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. \n The only kind of parent resource + with \"Core\" support is Gateway. This API may be extended in the + future to support additional kinds of parent resources such as one + of the route kinds. \n It is invalid to reference an identical parent + more than once. It is valid to reference multiple distinct sections + within the same parent resource, such as 2 Listeners within a Gateway. + \n It is possible to separately reference multiple distinct objects + that may be collapsed by an implementation. For example, some implementations + may choose to merge compatible Gateway Listeners together. If that + is the case, the list of routes attached to those resources should + also be merged." + items: + description: "ParentRef identifies an API object (usually a Gateway) + that can be considered a parent of this resource (usually a route). + The only kind of parent resource with \"Core\" support is Gateway. + This API may be extended in the future to support additional kinds + of parent resources, such as HTTPRoute. \n The API object must + be valid in the cluster; the Group and Kind must be registered + in the cluster for this reference to be valid. \n References to + objects with invalid Group and Kind are not valid, and must be + rejected by the implementation, with appropriate Conditions set + on the containing object." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + 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: Gateway + description: "Kind is kind of the referent. \n Support: Core + (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified (or empty string), this refers to the local namespace + of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name + \n Implementations MAY choose to support attaching Routes + to other resources. If that is the case, they MUST clearly + document how SectionName is interpreted. \n When unspecified + (empty string), this will reference the entire resource. For + the purpose of status, an attachment is considered successful + if at least one section in the parent resource accepts it. + For example, Gateway listeners can restrict which Routes can + attach to them by Route kind, namespace, or hostname. If 1 + of 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. \n + 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 + required: + - name + type: object + maxItems: 32 + type: array + rules: + description: Rules are a list of TCP matchers and actions. + items: + description: TCPRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching + requests should be sent. If unspecified or invalid (refers + to a non-existent resource or a Service with no endpoints), + the underlying implementation MUST actively reject connection + attempts to this backend. Connection rejections must respect + weight; if an invalid backend is requested to have 80% of + connections, then 80% of connections must be rejected instead. + \n Support: Core for Kubernetes Service Support: Custom for + any other resource \n Support for weight: Extended" + items: + description: "BackendRef defines how a Route should forward + a request to a Kubernetes resource. \n Note that when a + namespace is specified, a ReferencePolicy object is required + in the referent namespace to allow that namespace's owner + to accept the reference. See the ReferencePolicy documentation + for details." + properties: + group: + default: "" + description: Group is the group of the referent. For example, + "networking.k8s.io". When unspecified (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 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 + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace is specified, a ReferencePolicy + object is required in the referent namespace to allow + that namespace's owner to accept the reference. See + the ReferencePolicy documentation for details. \n 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. For other resources, + destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests + forwarded to the referenced backend. This is computed + as weight/(sum of all weights in this BackendRefs list). + For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision + an implementation supports. Weight is not a percentage + and the sum of weights does not need to equal 100. \n + If only one backend is specified and it has a weight + greater than 0, 100% of the traffic is forwarded to + that backend. If weight is set to 0, no traffic should + be forwarded for this entry. If unspecified, weight + defaults to 1. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + maxItems: 16 + minItems: 1 + type: array + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - rules + type: object + status: + description: Status defines the current state of TCPRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) + that are associated with the route, and the status of the route + with respect to each parent. When this route attaches to a parent, + the controller that manages the parent must add an entry to this + list when the controller first sees the route and should update + the entry as appropriate when the route or gateway is modified. + \n Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this + API can only populate Route status for the Gateways/parent resources + they are responsible for. \n A maximum of 32 Gateways will be represented + in this list. An empty list means the route has not been attached + to any Gateway." + items: + description: RouteParentStatus describes the status of a route with + respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with + respect to the Gateway. Note that the route's availability + is also subject to the Gateway's own status conditions and + listener status. \n If the Route's ParentRef specifies an + existing Gateway that supports Routes of this kind AND that + Gateway's controller has sufficient access, then that Gateway's + controller MUST set the \"Accepted\" condition on the Route, + to indicate whether the route has been accepted or rejected + by the Gateway, and why. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec + that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + 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: Gateway + description: "Kind is kind of the referent. \n Support: + Core (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified (or empty string), this refers to the + local namespace of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name \n Implementations MAY choose to support attaching + Routes to other resources. If that is the case, they MUST + clearly document how SectionName is interpreted. \n When + unspecified (empty string), this will reference the entire + resource. For the purpose of status, an attachment is + considered successful if at least one section in the parent + resource accepts it. For example, Gateway listeners can + restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept + attachment from the referencing Route, the Route MUST + be considered successfully attached. If no Gateway listeners + accept attachment from this Route, the Route MUST be considered + detached from the Gateway. \n 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 + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + creationTimestamp: null + name: tlsroutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: TLSRoute + listKind: TLSRouteList + plural: tlsroutes + singular: tlsroute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: "The TLSRoute resource is similar to TCPRoute, but can be configured + to match against TLS-specific metadata. This allows more flexibility in + matching streams for a given TLS listener. \n If you need to forward traffic + to a single target for a TLS listener, you could choose to use a TCPRoute + with a TLS listener." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of TLSRoute. + properties: + hostnames: + description: "Hostnames defines a set of SNI names that should match + against the SNI attribute of TLS ClientHello message in TLS handshake. + This matches the RFC 1123 definition of a hostname with 2 notable + exceptions: \n 1. IPs are not allowed in SNI names per RFC 6066. + 2. A hostname may be prefixed with a wildcard label (`*.`). The + wildcard label must appear by itself as the first label. \n If + a hostname is specified by both the Listener and TLSRoute, there + must be at least one intersecting hostname for the TLSRoute to be + attached to the Listener. For example: \n * A Listener with `test.example.com` + as the hostname matches TLSRoutes that have either not specified + any hostnames, or have specified at least one of `test.example.com` + or `*.example.com`. * A Listener with `*.example.com` as the hostname + matches TLSRoutes that have either not specified any hostnames + or have specified at least one hostname that matches the Listener + hostname. For example, `test.example.com` and `*.example.com` + would both match. On the other hand, `example.com` and `test.example.net` + would not match. \n If both the Listener and TLSRoute have specified + hostnames, any TLSRoute hostnames that do not match the Listener + hostname MUST be ignored. For example, if a Listener specified `*.example.com`, + and the TLSRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. \n If both + the Listener and TLSRoute have specified hostnames, and none match + with the criteria above, then the TLSRoute is not accepted. The + implementation must raise an 'Accepted' Condition with a status + of `False` in the corresponding RouteParentStatus. \n Support: Core" + items: + description: "Hostname is the fully qualified domain name of a network + host. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname + may be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n Hostname can be \"precise\" + which is a domain name without the terminating dot of a network + host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain + name prefixed with a single wildcard label (e.g. `*.example.com`). + \n Note that as per RFC1035 and RFC1123, a *label* must consist + of lower case alphanumeric characters or '-', and must start and + end with an alphanumeric character. No other punctuation is allowed." + 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 + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) + that a Route wants to be attached to. Note that the referenced parent + resource needs to allow this for the attachment to be complete. + For Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. \n The only kind of parent resource + with \"Core\" support is Gateway. This API may be extended in the + future to support additional kinds of parent resources such as one + of the route kinds. \n It is invalid to reference an identical parent + more than once. It is valid to reference multiple distinct sections + within the same parent resource, such as 2 Listeners within a Gateway. + \n It is possible to separately reference multiple distinct objects + that may be collapsed by an implementation. For example, some implementations + may choose to merge compatible Gateway Listeners together. If that + is the case, the list of routes attached to those resources should + also be merged." + items: + description: "ParentRef identifies an API object (usually a Gateway) + that can be considered a parent of this resource (usually a route). + The only kind of parent resource with \"Core\" support is Gateway. + This API may be extended in the future to support additional kinds + of parent resources, such as HTTPRoute. \n The API object must + be valid in the cluster; the Group and Kind must be registered + in the cluster for this reference to be valid. \n References to + objects with invalid Group and Kind are not valid, and must be + rejected by the implementation, with appropriate Conditions set + on the containing object." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + 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: Gateway + description: "Kind is kind of the referent. \n Support: Core + (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified (or empty string), this refers to the local namespace + of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name + \n Implementations MAY choose to support attaching Routes + to other resources. If that is the case, they MUST clearly + document how SectionName is interpreted. \n When unspecified + (empty string), this will reference the entire resource. For + the purpose of status, an attachment is considered successful + if at least one section in the parent resource accepts it. + For example, Gateway listeners can restrict which Routes can + attach to them by Route kind, namespace, or hostname. If 1 + of 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. \n + 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 + required: + - name + type: object + maxItems: 32 + type: array + rules: + description: Rules are a list of TLS matchers and actions. + items: + description: TLSRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching + requests should be sent. If unspecified or invalid (refers + to a non-existent resource or a Service with no endpoints), + the rule performs no forwarding; if no filters are specified + that would result in a response being sent, the underlying + implementation must actively reject request attempts to this + backend, by rejecting the connection or returning a 503 status + code. Request rejections must respect weight; if an invalid + backend is requested to have 80% of requests, then 80% of + requests must be rejected instead. \n Support: Core for Kubernetes + Service Support: Custom for any other resource \n Support + for weight: Extended" + items: + description: "BackendRef defines how a Route should forward + a request to a Kubernetes resource. \n Note that when a + namespace is specified, a ReferencePolicy object is required + in the referent namespace to allow that namespace's owner + to accept the reference. See the ReferencePolicy documentation + for details." + properties: + group: + default: "" + description: Group is the group of the referent. For example, + "networking.k8s.io". When unspecified (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 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 + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace is specified, a ReferencePolicy + object is required in the referent namespace to allow + that namespace's owner to accept the reference. See + the ReferencePolicy documentation for details. \n 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. For other resources, + destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests + forwarded to the referenced backend. This is computed + as weight/(sum of all weights in this BackendRefs list). + For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision + an implementation supports. Weight is not a percentage + and the sum of weights does not need to equal 100. \n + If only one backend is specified and it has a weight + greater than 0, 100% of the traffic is forwarded to + that backend. If weight is set to 0, no traffic should + be forwarded for this entry. If unspecified, weight + defaults to 1. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + maxItems: 16 + minItems: 1 + type: array + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - rules + type: object + status: + description: Status defines the current state of TLSRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) + that are associated with the route, and the status of the route + with respect to each parent. When this route attaches to a parent, + the controller that manages the parent must add an entry to this + list when the controller first sees the route and should update + the entry as appropriate when the route or gateway is modified. + \n Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this + API can only populate Route status for the Gateways/parent resources + they are responsible for. \n A maximum of 32 Gateways will be represented + in this list. An empty list means the route has not been attached + to any Gateway." + items: + description: RouteParentStatus describes the status of a route with + respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with + respect to the Gateway. Note that the route's availability + is also subject to the Gateway's own status conditions and + listener status. \n If the Route's ParentRef specifies an + existing Gateway that supports Routes of this kind AND that + Gateway's controller has sufficient access, then that Gateway's + controller MUST set the \"Accepted\" condition on the Route, + to indicate whether the route has been accepted or rejected + by the Gateway, and why. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec + that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + 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: Gateway + description: "Kind is kind of the referent. \n Support: + Core (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified (or empty string), this refers to the + local namespace of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name \n Implementations MAY choose to support attaching + Routes to other resources. If that is the case, they MUST + clearly document how SectionName is interpreted. \n When + unspecified (empty string), this will reference the entire + resource. For the purpose of status, an attachment is + considered successful if at least one section in the parent + resource accepts it. For example, Gateway listeners can + restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept + attachment from the referencing Route, the Route MUST + be considered successfully attached. If no Gateway listeners + accept attachment from this Route, the Route MUST be considered + detached from the Gateway. \n 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 + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/integration/fixtures/k8s/01-gateway-api.yml b/integration/fixtures/k8s/01-gateway-api.yml deleted file mode 100644 index 8a7da2c7d..000000000 --- a/integration/fixtures/k8s/01-gateway-api.yml +++ /dev/null @@ -1,2710 +0,0 @@ - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - name: gatewayclasses.networking.x-k8s.io -spec: - group: networking.x-k8s.io - names: - categories: - - gateway-api - kind: GatewayClass - listKind: GatewayClassList - plural: gatewayclasses - shortNames: - - gc - singular: gatewayclass - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.controller - name: Controller - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: "GatewayClass describes a class of Gateways available to the - user for creating Gateway resources. \n GatewayClass is a Cluster level - resource." - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of GatewayClass. - properties: - controller: - description: "Controller is a domain/path string that indicates the - controller that is managing Gateways of this class. \n Example: - \"acme.io/gateway-controller\". \n This field is not mutable and - cannot be empty. \n The format of this field is DOMAIN \"/\" PATH, - where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). - \n Support: Core" - maxLength: 253 - type: string - parametersRef: - description: "ParametersRef is a reference to a resource that contains - the configuration parameters corresponding to the GatewayClass. - This is optional if the controller does not require any additional - configuration. \n ParametersRef can reference a standard Kubernetes - resource, i.e. ConfigMap, or an implementation-specific custom resource. - The resource can be cluster-scoped or namespace-scoped. \n If the - referent cannot be found, the GatewayClass's \"InvalidParameters\" - status condition will be true. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - 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 referent. This - field is required when scope is set to "Namespace" and ignored - when scope is set to "Cluster". - maxLength: 253 - minLength: 1 - type: string - scope: - default: Cluster - description: Scope represents if the referent is a Cluster or - Namespace scoped resource. This may be set to "Cluster" or "Namespace". - enum: - - Cluster - - Namespace - type: string - required: - - group - - kind - - name - type: object - required: - - controller - type: object - status: - default: - conditions: - - lastTransitionTime: "1970-01-01T00:00:00Z" - message: Waiting for controller - reason: Waiting - status: "False" - type: Admitted - description: Status defines the current state of GatewayClass. - properties: - conditions: - default: - - lastTransitionTime: "1970-01-01T00:00:00Z" - message: Waiting for controller - reason: Waiting - status: "False" - type: Admitted - description: "Conditions is the current status from the controller - for this GatewayClass. \n Controllers should prefer to publish conditions - using values of GatewayClassConditionType for the type of each Condition." - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - maxItems: 8 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - name: gateways.networking.x-k8s.io -spec: - group: networking.x-k8s.io - names: - categories: - - gateway-api - kind: Gateway - listKind: GatewayList - plural: gateways - shortNames: - - gtw - singular: gateway - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.gatewayClassName - name: Class - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: "Gateway represents an instantiation of a service-traffic handling - infrastructure by binding Listeners to a set of IP addresses. \n Implementations - should add the `gateway-exists-finalizer.networking.x-k8s.io` finalizer - on the associated GatewayClass whenever Gateway(s) is running. This ensures - that a GatewayClass associated with a Gateway(s) is not deleted while in - use." - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of Gateway. - properties: - addresses: - description: "Addresses requested for this gateway. This is optional - and behavior can depend on the GatewayClass. If a value is set in - the spec and the requested address is invalid, the GatewayClass - MUST indicate this in the associated entry in GatewayStatus.Addresses. - \n If no Addresses are specified, the GatewayClass may schedule - the Gateway in an implementation-defined manner, assigning an appropriate - set of Addresses. \n The GatewayClass MUST bind all Listeners to - every GatewayAddress that it assigns to the Gateway. \n Support: - Core" - items: - description: GatewayAddress describes an address that can be bound - to a Gateway. - properties: - type: - default: IPAddress - description: "Type of the address. \n Support: Extended" - enum: - - IPAddress - - NamedAddress - type: string - value: - description: "Value of the address. The validity of the values - will depend on the type and support by the controller. \n - Examples: `1.2.3.4`, `128::1`, `my-ip-address`." - maxLength: 253 - minLength: 1 - type: string - required: - - value - type: object - maxItems: 16 - type: array - gatewayClassName: - description: GatewayClassName used for this Gateway. This is the name - of a GatewayClass resource. - maxLength: 253 - minLength: 1 - type: string - listeners: - description: "Listeners associated with this Gateway. Listeners define - logical endpoints that are bound on this Gateway's addresses. At - least one Listener MUST be specified. \n An implementation MAY group - Listeners by Port and then collapse each group of Listeners into - a single Listener if the implementation determines that the Listeners - in the group are \"compatible\". An implementation MAY also group - together and collapse compatible Listeners belonging to different - Gateways. \n For example, an implementation might consider Listeners - to be compatible with each other if all of the following conditions - are met: \n 1. Either each Listener within the group specifies the - \"HTTP\" Protocol or each Listener within the group specifies - either the \"HTTPS\" or \"TLS\" Protocol. \n 2. Each Listener - within the group specifies a Hostname that is unique within the - group. \n 3. As a special case, one Listener within a group may - omit Hostname, in which case this Listener matches when no other - Listener matches. \n If the implementation does collapse compatible - Listeners, the hostname provided in the incoming client request - MUST be matched to a Listener to find the correct set of Routes. - The incoming hostname MUST be matched using the Hostname field for - each Listener in order of most to least specific. That is, exact - matches must be processed before wildcard matches. \n If this field - specifies multiple Listeners that have the same Port value but are - not compatible, the implementation must raise a \"Conflicted\" condition - in the Listener status. \n Support: Core" - items: - description: Listener embodies the concept of a logical endpoint - where a Gateway can accept network connections. Each listener - in a Gateway must have a unique combination of Hostname, Port, - and Protocol. This will be enforced by a validating webhook. - properties: - hostname: - description: "Hostname specifies the virtual hostname to match - for protocol types that define this concept. When unspecified, - \"\", or `*`, all hostnames are matched. This field can be - omitted for protocols that don't require hostname based matching. - \n Hostname is the fully qualified domain name of a network - host, as defined by RFC 3986. Note the following deviations - from the \"host\" part of the URI as defined in the RFC: \n - 1. IP literals are not allowed. 2. The `:` delimiter is not - respected because ports are not allowed. \n Hostname can be - \"precise\" which is a domain name without the terminating - dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", - which is a domain name prefixed with a single wildcard label - (e.g. `*.example.com`). The wildcard character `*` must appear - by itself as the first DNS label and matches only a single - label. \n Support: Core" - maxLength: 253 - minLength: 1 - type: string - port: - description: "Port is the network port. Multiple listeners may - use the same port, subject to the Listener compatibility rules. - \n Support: Core" - format: int32 - maximum: 65535 - minimum: 1 - type: integer - protocol: - description: "Protocol specifies the network protocol this listener - expects to receive. The GatewayClass MUST apply the Hostname - match appropriately for each protocol: \n * For the \"TLS\" - protocol, the Hostname match MUST be applied to the [SNI](https://tools.ietf.org/html/rfc6066#section-3) - \ server name offered by the client. * For the \"HTTP\" protocol, - the Hostname match MUST be applied to the host portion of - the [effective request URI](https://tools.ietf.org/html/rfc7230#section-5.5) - \ or the [:authority pseudo-header](https://tools.ietf.org/html/rfc7540#section-8.1.2.3) - * For the \"HTTPS\" protocol, the Hostname match MUST be applied - at both the TLS and HTTP protocol layers. \n Support: Core" - type: string - routes: - description: "Routes specifies a schema for associating routes - with the Listener using selectors. A Route is a resource capable - of servicing a request and allows a cluster operator to expose - a cluster resource (i.e. Service) by externally-reachable - URL, load-balance traffic and terminate SSL/TLS. Typically, - a route is a \"HTTPRoute\" or \"TCPRoute\" in group \"networking.x-k8s.io\", - however, an implementation may support other types of resources. - \n The Routes selector MUST select a set of objects that are - compatible with the application protocol specified in the - Protocol field. \n Although a client request may technically - match multiple route rules, only one rule may ultimately receive - the request. Matching precedence MUST be determined in order - of the following criteria: \n * The most specific match. For - example, the most specific HTTPRoute match is determined - by the longest matching combination of hostname and path. - * The oldest Route based on creation timestamp. For example, - a Route with a creation timestamp of \"2020-09-08 01:02:03\" - is given precedence over a Route with a creation timestamp - of \"2020-09-08 01:02:04\". * If everything else is equivalent, - the Route appearing first in alphabetical order (namespace/name) - should be given precedence. For example, foo/bar is given - precedence over foo/baz. \n All valid portions of a Route - selected by this field should be supported. Invalid portions - of a Route can be ignored (sometimes that will mean the full - Route). If a portion of a Route transitions from valid to - invalid, support for that portion of the Route should be dropped - to ensure consistency. For example, even if a filter specified - by a Route is invalid, the rest of the Route should still - be supported. \n Support: Core" - properties: - group: - default: networking.x-k8s.io - description: "Group is the group of the route resource to - select. Omitting the value or specifying the empty string - indicates the networking.x-k8s.io API group. For example, - use the following to select an HTTPRoute: \n routes: kind: - HTTPRoute \n Otherwise, if an alternative API group is - desired, specify the desired group: \n routes: group: - acme.io kind: FooRoute \n Support: Core" - maxLength: 253 - minLength: 1 - type: string - kind: - description: "Kind is the kind of the route resource to - select. \n Kind MUST correspond to kinds of routes that - are compatible with the application protocol specified - in the Listener's Protocol field. \n If an implementation - does not support or recognize this resource type, it SHOULD - set the \"ResolvedRefs\" condition to false for this listener - with the \"InvalidRoutesRef\" reason. \n Support: Core" - type: string - namespaces: - default: - from: Same - description: "Namespaces indicates in which namespaces Routes - should be selected for this Gateway. This is restricted - to the namespace of this Gateway by default. \n Support: - Core" - properties: - from: - default: Same - description: "From indicates where Routes will be selected - for this Gateway. Possible values are: * All: Routes - in all namespaces may be used by this Gateway. * Selector: - Routes in namespaces selected by the selector may - be used by this Gateway. * Same: Only Routes in - the same namespace may be used by this Gateway. \n - Support: Core" - enum: - - All - - Selector - - Same - type: string - selector: - description: "Selector must be specified when From is - set to \"Selector\". In that case, only Routes in - Namespaces matching this Selector will be selected - by this Gateway. This field is ignored for other values - of \"From\". \n Support: Core" - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a - selector that contains values, a key, and an - operator that relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are - In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. If the - operator is Exists or DoesNotExist, the - values array must be empty. This array is - replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is "In", - and the values array contains only "value". The - requirements are ANDed. - type: object - type: object - type: object - selector: - description: "Selector specifies a set of route labels used - for selecting routes to associate with the Gateway. If - this Selector is defined, only routes matching the Selector - are associated with the Gateway. An empty Selector matches - all routes. \n Support: Core" - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. - If the operator is In or NotIn, the values array - must be non-empty. If the operator is Exists - or DoesNotExist, the values array must be empty. - This array is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. - A single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field - is "key", the operator is "In", and the values array - contains only "value". The requirements are ANDed. - type: object - type: object - required: - - kind - type: object - tls: - description: "TLS is the TLS configuration for the Listener. - This field is required if the Protocol field is \"HTTPS\" - or \"TLS\" and ignored otherwise. \n The association of SNIs - to Certificate defined in GatewayTLSConfig is defined based - on the Hostname field for this listener. \n The GatewayClass - MUST use the longest matching SNI out of all available certificates - for any TLS handshake. \n Support: Core" - properties: - certificateRef: - description: "CertificateRef is a reference to a Kubernetes - object that contains a TLS certificate and private key. - This certificate is used to establish a TLS handshake - for requests that match the hostname of the associated - listener. The referenced object MUST reside in the same - namespace as Gateway. \n This field is required when mode - is set to \"Terminate\" (default) and optional otherwise. - \n CertificateRef can reference a standard Kubernetes - resource, i.e. Secret, or an implementation-specific custom - resource. \n Support: Core (Kubernetes Secrets) \n Support: - Implementation-specific (Other resource types)" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - mode: - default: Terminate - description: "Mode defines the TLS behavior for the TLS - session initiated by the client. There are two possible - modes: - Terminate: The TLS session between the downstream - client and the Gateway is terminated at the Gateway. - This mode requires certificateRef to be set. - Passthrough: - The TLS session is NOT terminated by the Gateway. This - \ implies that the Gateway can't decipher the TLS stream - except for the ClientHello message of the TLS protocol. - \ CertificateRef field is ignored in this mode. \n Support: - Core" - enum: - - Terminate - - Passthrough - type: string - options: - additionalProperties: - type: string - description: "Options are a list of key/value pairs to give - extended options to the provider. \n There variation among - providers as to how ciphersuites are expressed. If there - is a common subset for expressing ciphers then it will - make sense to loft that as a core API construct. \n Support: - Implementation-specific" - type: object - routeOverride: - default: - certificate: Deny - description: "RouteOverride dictates if TLS settings can - be configured via Routes or not. \n CertificateRef must - be defined even if `routeOverride.certificate` is set - to 'Allow' as it will be used as the default certificate - for the listener. \n Support: Core" - properties: - certificate: - default: Deny - description: "Certificate dictates if TLS certificates - can be configured via Routes. If set to 'Allow', a - TLS certificate for a hostname defined in a Route - takes precedence over the certificate defined in Gateway. - \n Support: Core" - enum: - - Allow - - Deny - type: string - type: object - type: object - required: - - port - - protocol - - routes - type: object - maxItems: 64 - minItems: 1 - type: array - required: - - gatewayClassName - - listeners - type: object - status: - default: - conditions: - - lastTransitionTime: "1970-01-01T00:00:00Z" - message: Waiting for controller - reason: NotReconciled - status: "False" - type: Scheduled - description: Status defines the current state of Gateway. - properties: - addresses: - description: "Addresses lists the IP addresses that have actually - been bound to the Gateway. These addresses may differ from the addresses - in the Spec, e.g. if the Gateway automatically assigns an address - from a reserved pool. \n These addresses should all be of type \"IPAddress\"." - items: - description: GatewayAddress describes an address that can be bound - to a Gateway. - properties: - type: - default: IPAddress - description: "Type of the address. \n Support: Extended" - enum: - - IPAddress - - NamedAddress - type: string - value: - description: "Value of the address. The validity of the values - will depend on the type and support by the controller. \n - Examples: `1.2.3.4`, `128::1`, `my-ip-address`." - maxLength: 253 - minLength: 1 - type: string - required: - - value - type: object - maxItems: 16 - type: array - conditions: - default: - - lastTransitionTime: "1970-01-01T00:00:00Z" - message: Waiting for controller - reason: NotReconciled - status: "False" - type: Scheduled - description: "Conditions describe the current conditions of the Gateway. - \n Implementations should prefer to express Gateway conditions using - the `GatewayConditionType` and `GatewayConditionReason` constants - so that operators and tools can converge on a common vocabulary - to describe Gateway state. \n Known condition types are: \n * \"Scheduled\" - * \"Ready\"" - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - maxItems: 8 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - listeners: - description: Listeners provide status for each unique listener port - defined in the Spec. - items: - description: ListenerStatus is the status associated with a Listener. - properties: - conditions: - description: Conditions describe the current condition of this - listener. - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - maxItems: 8 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - hostname: - description: Hostname is the Listener hostname value for which - this message is reporting the status. - maxLength: 253 - minLength: 1 - type: string - port: - description: Port is the unique Listener port value for which - this message is reporting the status. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - protocol: - description: Protocol is the Listener protocol value for which - this message is reporting the status. - type: string - required: - - conditions - - port - - protocol - type: object - maxItems: 64 - type: array - x-kubernetes-list-map-keys: - - port - x-kubernetes-list-type: map - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - name: httproutes.networking.x-k8s.io -spec: - group: networking.x-k8s.io - names: - categories: - - gateway-api - kind: HTTPRoute - listKind: HTTPRouteList - plural: httproutes - singular: httproute - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.hostnames - name: Hostnames - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: HTTPRoute is the Schema for the HTTPRoute resource. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of HTTPRoute. - properties: - gateways: - default: - allow: SameNamespace - description: Gateways defines which Gateways can use this Route. - properties: - allow: - default: SameNamespace - description: 'Allow indicates which Gateways will be allowed to - use this route. Possible values are: * All: Gateways in any - namespace can use this route. * FromList: Only Gateways specified - in GatewayRefs may use this route. * SameNamespace: Only Gateways - in the same namespace may use this route.' - enum: - - All - - FromList - - SameNamespace - type: string - gatewayRefs: - description: GatewayRefs must be specified when Allow is set to - "FromList". In that case, only Gateways referenced in this list - will be allowed to use this route. This field is ignored for - other values of "Allow". - items: - description: GatewayReference identifies a Gateway in a specified - namespace. - properties: - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace is the namespace of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - namespace - type: object - type: array - type: object - hostnames: - description: "Hostnames defines a set of hostname that should match - against the HTTP Host header to select a HTTPRoute to process the - request. Hostname is the fully qualified domain name of a network - host, as defined by RFC 3986. Note the following deviations from - the \"host\" part of the URI as defined in the RFC: \n 1. IPs are - not allowed. 2. The `:` delimiter is not respected because ports - are not allowed. \n Incoming requests are matched against the hostnames - before the HTTPRoute rules. If no hostname is specified, traffic - is routed based on the HTTPRouteRules. \n Hostname can be \"precise\" - which is a domain name without the terminating dot of a network - host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain - name prefixed with a single wildcard label (e.g. `*.example.com`). - The wildcard character `*` must appear by itself as the first DNS - label and matches only a single label. You cannot have a wildcard - label by itself (e.g. Host == `*`). Requests will be matched against - the Host field in the following order: \n 1. If Host is precise, - the request matches this rule if the HTTP Host header is equal - to Host. 2. If Host is a wildcard, then the request matches this - rule if the HTTP Host header is to equal to the suffix (removing - the first label) of the wildcard rule. \n Support: Core" - items: - description: Hostname is used to specify a hostname that should - be matched. - maxLength: 253 - minLength: 1 - type: string - maxItems: 16 - type: array - rules: - default: - - matches: - - path: - type: Prefix - value: / - description: Rules are a list of HTTP matchers, filters and actions. - items: - description: HTTPRouteRule defines semantics for matching an HTTP - request based on conditions, optionally executing additional processing - steps, and forwarding the request to an API object. - properties: - filters: - description: "Filters define the filters that are applied to - requests that match this rule. \n The effects of ordering - of multiple behaviors are currently unspecified. This can - change in the future based on feedback during the alpha stage. - \n Conformance-levels at this level are defined based on the - type of filter: \n - ALL core filters MUST be supported by - all implementations. - Implementers are encouraged to support - extended filters. - Implementation-specific custom filters - have no API guarantees across implementations. \n Specifying - a core filter multiple times has unspecified or custom conformance. - \n Support: Core" - items: - description: 'HTTPRouteFilter defines additional processing - steps that must be completed during the request or response - lifecycle. HTTPRouteFilters are meant as an extension point - to express additional 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. TODO(hbagdi): re-render - CRDs once controller-tools supports union tags: - https://github.com/kubernetes-sigs/controller-tools/pull/298 - - https://github.com/kubernetes-sigs/controller-tools/issues/461' - properties: - extensionRef: - description: "ExtensionRef is an optional, implementation-specific - extension to the \"filter\" behavior. For example, - resource \"myroutefilter\" in group \"networking.acme.io\"). - ExtensionRef MUST NOT be used for core and extended - filters. \n Support: Implementation-specific" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - requestHeaderModifier: - description: "RequestHeaderModifier defines a schema for - a filter that modifies request headers. \n Support: - Core" - properties: - add: - additionalProperties: - type: string - description: "Add adds the given header (name, value) - to the request before the action. It appends to - any existing values associated with the header name. - \n Input: GET /foo HTTP/1.1 my-header: foo \n - Config: add: {\"my-header\": \"bar\"} \n Output: - \ GET /foo HTTP/1.1 my-header: foo my-header: - bar \n Support: Extended" - type: object - remove: - description: "Remove the given header(s) from the - HTTP request before the action. The value of RemoveHeader - is a list of HTTP header names. Note that the header - names are case-insensitive [RFC-2616 4.2]. \n Input: - \ GET /foo HTTP/1.1 my-header1: foo my-header2: - bar my-header3: baz \n Config: remove: [\"my-header1\", - \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: - bar \n Support: Extended" - items: - type: string - maxItems: 16 - type: array - set: - additionalProperties: - type: string - description: "Set overwrites the request with the - given header (name, value) before the action. \n - Input: GET /foo HTTP/1.1 my-header: foo \n Config: - \ set: {\"my-header\": \"bar\"} \n Output: GET - /foo HTTP/1.1 my-header: bar \n Support: Extended" - type: object - type: object - requestMirror: - description: "RequestMirror defines a schema for a filter - that mirrors requests. \n Support: Extended" - properties: - backendRef: - description: "BackendRef is a local object reference - to mirror matched requests to. If both BackendRef - and ServiceName are specified, ServiceName will - be given precedence. \n If the referent cannot be - found, the rule is not included in the route. The - controller should raise the \"ResolvedRefs\" condition - on the Gateway with the \"DegradedRoutes\" reason. - The gateway status for this route should be updated - with a condition that describes the error more specifically. - \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - port: - description: "Port specifies the destination port - number to use for the backend referenced by the - ServiceName or BackendRef field. \n If unspecified, - the destination port in the request is used when - forwarding to a backendRef or serviceName." - format: int32 - maximum: 65535 - minimum: 1 - type: integer - serviceName: - description: "ServiceName refers to the name of the - Service to mirror matched requests to. When specified, - this takes the place of BackendRef. If both BackendRef - and ServiceName are specified, ServiceName will - be given precedence. \n If the referent cannot be - found, the rule is not included in the route. The - controller should raise the \"ResolvedRefs\" condition - on the Gateway with the \"DegradedRoutes\" reason. - The gateway status for this route should be updated - with a condition that describes the error more specifically. - \n Support: Core" - maxLength: 253 - type: string - type: object - type: - description: "Type identifies the type of filter to apply. - As with other API fields, types are classified into - three conformance levels: \n - Core: Filter types and - their corresponding configuration defined by \"Support: - Core\" in this package, e.g. \"RequestHeaderModifier\". - All implementations must support core filters. \n - - Extended: Filter types and their corresponding configuration - defined by \"Support: Extended\" in this package, - e.g. \"RequestMirror\". Implementers are encouraged - to support extended filters. \n - Custom: 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. \n - Implementers are encouraged to define custom implementation - types to extend the core API with implementation-specific - behavior." - enum: - - RequestHeaderModifier - - RequestMirror - - ExtensionRef - type: string - required: - - type - type: object - maxItems: 16 - type: array - forwardTo: - description: ForwardTo defines the backend(s) where matching - requests should be sent. If unspecified, the rule performs - no forwarding. If unspecified and no filters are specified - that would result in a response being sent, a 503 error code - is returned. - items: - description: HTTPRouteForwardTo defines how a HTTPRoute should - forward a request. - properties: - backendRef: - description: "BackendRef is a reference to a backend to - forward matched requests to. If both BackendRef and - ServiceName are specified, ServiceName will be given - precedence. \n If the referent cannot be found, the - route must be dropped from the Gateway. The controller - should raise the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway status - for this route should be updated with a condition that - describes the error more specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - filters: - description: "Filters defined at this-level should be - executed if and only if the request is being forwarded - to the backend defined here. \n Support: Custom (For - broader support of filters, use the Filters field in - HTTPRouteRule.)" - items: - description: 'HTTPRouteFilter defines additional processing - steps that must be completed during the request or - response lifecycle. HTTPRouteFilters are meant as - an extension point to express additional 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. TODO(hbagdi): - re-render CRDs once controller-tools supports union - tags: - https://github.com/kubernetes-sigs/controller-tools/pull/298 - - https://github.com/kubernetes-sigs/controller-tools/issues/461' - properties: - extensionRef: - description: "ExtensionRef is an optional, implementation-specific - extension to the \"filter\" behavior. For example, - resource \"myroutefilter\" in group \"networking.acme.io\"). - ExtensionRef MUST NOT be used for core and extended - filters. \n Support: Implementation-specific" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - requestHeaderModifier: - description: "RequestHeaderModifier defines a schema - for a filter that modifies request headers. \n - Support: Core" - properties: - add: - additionalProperties: - type: string - description: "Add adds the given header (name, - value) to the request before the action. It - appends to any existing values associated - with the header name. \n Input: GET /foo - HTTP/1.1 my-header: foo \n Config: add: - {\"my-header\": \"bar\"} \n Output: GET - /foo HTTP/1.1 my-header: foo my-header: - bar \n Support: Extended" - type: object - remove: - description: "Remove the given header(s) from - the HTTP request before the action. The value - of RemoveHeader is a list of HTTP header names. - Note that the header names are case-insensitive - [RFC-2616 4.2]. \n Input: GET /foo HTTP/1.1 - \ my-header1: foo my-header2: bar my-header3: - baz \n Config: remove: [\"my-header1\", - \"my-header3\"] \n Output: GET /foo HTTP/1.1 - \ my-header2: bar \n Support: Extended" - items: - type: string - maxItems: 16 - type: array - set: - additionalProperties: - type: string - description: "Set overwrites the request with - the given header (name, value) before the - action. \n Input: GET /foo HTTP/1.1 my-header: - foo \n Config: set: {\"my-header\": \"bar\"} - \n Output: GET /foo HTTP/1.1 my-header: - bar \n Support: Extended" - type: object - type: object - requestMirror: - description: "RequestMirror defines a schema for - a filter that mirrors requests. \n Support: Extended" - properties: - backendRef: - description: "BackendRef is a local object reference - to mirror matched requests to. If both BackendRef - and ServiceName are specified, ServiceName - will be given precedence. \n If the referent - cannot be found, the rule is not included - in the route. The controller should raise - the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway - status for this route should be updated with - a condition that describes the error more - specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - port: - description: "Port specifies the destination - port number to use for the backend referenced - by the ServiceName or BackendRef field. \n - If unspecified, the destination port in the - request is used when forwarding to a backendRef - or serviceName." - format: int32 - maximum: 65535 - minimum: 1 - type: integer - serviceName: - description: "ServiceName refers to the name - of the Service to mirror matched requests - to. When specified, this takes the place of - BackendRef. If both BackendRef and ServiceName - are specified, ServiceName will be given precedence. - \n If the referent cannot be found, the rule - is not included in the route. The controller - should raise the \"ResolvedRefs\" condition - on the Gateway with the \"DegradedRoutes\" - reason. The gateway status for this route - should be updated with a condition that describes - the error more specifically. \n Support: Core" - maxLength: 253 - type: string - type: object - type: - description: "Type identifies the type of filter - to apply. As with other API fields, types are - classified into three conformance levels: \n - - Core: Filter types and their corresponding configuration - defined by \"Support: Core\" in this package, - e.g. \"RequestHeaderModifier\". All implementations - must support core filters. \n - Extended: Filter - types and their corresponding configuration defined - by \"Support: Extended\" in this package, e.g. - \"RequestMirror\". Implementers are encouraged - to support extended filters. \n - Custom: 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. \n Implementers are encouraged - to define custom implementation types to extend - the core API with implementation-specific behavior." - enum: - - RequestHeaderModifier - - RequestMirror - - ExtensionRef - type: string - required: - - type - type: object - maxItems: 16 - type: array - port: - description: "Port specifies the destination port number - to use for the backend referenced by the ServiceName - or BackendRef field. If unspecified, the destination - port in the request is used when forwarding to a backendRef - or serviceName. \n Support: Core" - format: int32 - maximum: 65535 - minimum: 1 - type: integer - serviceName: - description: "ServiceName refers to the name of the Service - to forward matched requests to. When specified, this - takes the place of BackendRef. If both BackendRef and - ServiceName are specified, ServiceName will be given - precedence. \n If the referent cannot be found, the - route must be dropped from the Gateway. The controller - should raise the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway status - for this route should be updated with a condition that - describes the error more specifically. \n The protocol - to use should be specified with the AppProtocol field - on Service resources. This field was introduced in Kubernetes - 1.18. If using an earlier version of Kubernetes, a `networking.x-k8s.io/app-protocol` - annotation on the BackendPolicy resource may be used - to define the protocol. If the AppProtocol field is - available, this annotation should not be used. The AppProtocol - field, when populated, takes precedence over the annotation - in the BackendPolicy resource. For custom backends, - it is encouraged to add a semantically-equivalent field - in the Custom Resource Definition. \n Support: Core" - maxLength: 253 - type: string - weight: - default: 1 - description: "Weight specifies the proportion of HTTP - requests forwarded to the backend referenced by the - ServiceName or BackendRef field. This is computed as - weight/(sum of all weights in this ForwardTo list). - For non-zero values, there may be some epsilon from - the exact proportion defined here depending on the precision - an implementation supports. Weight is not a percentage - and the sum of weights does not need to equal 100. \n - If only one backend is specified and it has a weight - greater than 0, 100% of the traffic is forwarded to - that backend. If weight is set to 0, no traffic should - be forwarded for this entry. If unspecified, weight - defaults to 1. \n Support: Core" - format: int32 - maximum: 1000000 - minimum: 0 - type: integer - type: object - maxItems: 16 - type: array - matches: - default: - - path: - type: Prefix - value: / - description: "Matches define conditions used for matching the - rule against incoming HTTP requests. Each match is independent, - i.e. this rule will be matched if **any** one of the matches - is satisfied. \n For example, take the following matches configuration: - \n ``` matches: - path: value: \"/foo\" headers: values: - \ version: \"2\" - path: value: \"/v2/foo\" ``` \n - For a request to match against this rule, a request should - satisfy EITHER of the two conditions: \n - path prefixed with - `/foo` AND contains the header `version: \"2\"` - path prefix - of `/v2/foo` \n See the documentation for HTTPRouteMatch on - how to specify multiple match conditions that should be ANDed - together. \n If no matches are specified, the default is a - prefix path match on \"/\", which has the effect of matching - every HTTP request. \n Each client request MUST map to a maximum - of one route rule. If a request matches multiple rules, matching - precedence MUST be determined in order of the following criteria, - continuing on ties: \n * The longest matching hostname. * - The longest matching path. * The largest number of header - matches. \n If ties still exist across multiple Routes, matching - precedence MUST be determined in order of the following criteria, - continuing on ties: \n * The oldest Route based on creation - timestamp. For example, a Route with a creation timestamp - of \"2020-09-08 01:02:03\" is given precedence over a Route - with a creation timestamp of \"2020-09-08 01:02:04\". * The - Route appearing first in alphabetical order by \"/\". - For example, foo/bar is given precedence over foo/baz. \n - If ties still exist within the Route that has been given precedence, - matching precedence MUST be granted to the first matching - rule meeting the above criteria." - items: - description: "HTTPRouteMatch defines the predicate used to - match requests to a given action. Multiple match types are - ANDed together, i.e. the match will evaluate to true only - if all conditions are satisfied. \n For example, the match - below will match a HTTP request only if its path starts - with `/foo` AND it contains the `version: \"1\"` header: - \n ``` match: path: value: \"/foo\" headers: values: - \ version: \"1\" ```" - properties: - extensionRef: - description: "ExtensionRef is an optional, implementation-specific - extension to the \"match\" behavior. For example, resource - \"myroutematcher\" in group \"networking.acme.io\". - If the referent cannot be found, the rule is not included - in the route. The controller should raise the \"ResolvedRefs\" - condition on the Gateway with the \"DegradedRoutes\" - reason. The gateway status for this route should be - updated with a condition that describes the error more - specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - headers: - description: Headers specifies a HTTP request header matcher. - properties: - type: - default: Exact - description: "Type specifies how to match against - the value of the header. \n Support: Core (Exact) - \n Support: Custom (RegularExpression, ImplementationSpecific) - \n Since RegularExpression PathType has custom conformance, - implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the - implementation's documentation to determine the - supported dialect. \n HTTP Header name matching - MUST be case-insensitive (RFC 2616 - section 4.2)." - enum: - - Exact - - RegularExpression - - ImplementationSpecific - type: string - values: - additionalProperties: - type: string - description: "Values is a map of HTTP Headers to be - matched. It MUST contain at least one entry. \n - The HTTP header field name to match is the map key, - and the value of the HTTP header is the map value. - HTTP header field name matching MUST be case-insensitive. - \n Multiple match values are ANDed together, meaning, - a request must match all the specified headers to - select the route." - type: object - required: - - values - type: object - path: - default: - type: Prefix - value: / - description: Path specifies a HTTP request path matcher. - If this field is not specified, a default prefix match - on the "/" path is provided. - properties: - type: - default: Prefix - description: "Type specifies how to match against - the path Value. \n Support: Core (Exact, Prefix) - \n Support: Custom (RegularExpression, ImplementationSpecific) - \n Since RegularExpression PathType has custom conformance, - implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the - implementation's documentation to determine the - supported dialect." - enum: - - Exact - - Prefix - - RegularExpression - - ImplementationSpecific - type: string - value: - default: / - description: Value of the HTTP path to match against. - type: string - type: object - queryParams: - description: QueryParams specifies a HTTP query parameter - matcher. - properties: - type: - default: Exact - description: "Type specifies how to match against - the value of the query parameter. \n Support: Extended - (Exact) \n Support: Custom (RegularExpression, ImplementationSpecific) - \n Since RegularExpression QueryParamMatchType has - custom conformance, implementations can support - POSIX, PCRE or any other dialects of regular expressions. - Please read the implementation's documentation to - determine the supported dialect." - enum: - - Exact - - RegularExpression - - ImplementationSpecific - type: string - values: - additionalProperties: - type: string - description: "Values is a map of HTTP query parameters - to be matched. It MUST contain at least one entry. - \n The query parameter name to match is the map - key, and the value of the query parameter is the - map value. \n Multiple match values are ANDed together, - meaning, a request must match all the specified - query parameters to select the route. \n HTTP query - parameter matching MUST be case-sensitive for both - keys and values. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). - \n Note that the query parameter key MUST always - be an exact match by string comparison." - type: object - required: - - values - type: object - type: object - maxItems: 8 - type: array - type: object - maxItems: 16 - type: array - tls: - description: "TLS defines the TLS certificate to use for Hostnames - defined in this Route. This configuration only takes effect if the - AllowRouteOverride field is set to true in the associated Gateway - resource. \n Collisions can happen if multiple HTTPRoutes define - a TLS certificate for the same hostname. In such a case, conflict - resolution guiding principles apply, specifically, if hostnames - are same and two different certificates are specified then the certificate - in the oldest resource wins. \n Please note that HTTP Route-selection - takes place after the TLS Handshake (ClientHello). Due to this, - TLS certificate defined here will take precedence even if the request - has the potential to match multiple routes (in case multiple HTTPRoutes - share the same hostname). \n Support: Core" - properties: - certificateRef: - description: "CertificateRef is a reference to a Kubernetes object - that contains a TLS certificate and private key. This certificate - is used to establish a TLS handshake for requests that match - the hostname of the associated HTTPRoute. The referenced object - MUST reside in the same namespace as HTTPRoute. \n This field - is required when the TLS configuration mode of the associated - Gateway listener is set to \"Passthrough\". \n CertificateRef - can reference a standard Kubernetes resource, i.e. Secret, or - an implementation-specific custom resource. \n Support: Core - (Kubernetes Secrets) \n Support: Implementation-specific (Other - resource types)" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - required: - - certificateRef - type: object - type: object - status: - description: Status defines the current state of HTTPRoute. - properties: - gateways: - description: "Gateways is a list of Gateways that are associated with - the route, and the status of the route with respect to each Gateway. - When a Gateway selects this route, the controller that manages the - Gateway must add an entry to this list when the controller first - sees the route and should update the entry as appropriate when the - route is modified. \n A maximum of 100 Gateways will be represented - in this list. If this list is full, there may be additional Gateways - using this Route that are not included in the list. An empty list - means the route has not been admitted by any Gateway." - items: - description: RouteGatewayStatus describes the status of a route - with respect to an associated Gateway. - properties: - conditions: - description: Conditions describes the status of the route with - respect to the Gateway. The "Admitted" condition must always - be specified by controllers to indicate whether the route - has been admitted or rejected by the Gateway, and why. Note - that the route's availability is also subject to the Gateway's - own status conditions and listener status. - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - maxItems: 8 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - gatewayRef: - description: GatewayRef is a reference to a Gateway object that - is associated with the route. - properties: - controller: - description: "Controller is a domain/path string that indicates - the controller implementing the Gateway. This corresponds - with the controller field on GatewayClass. \n Example: - \"acme.io/gateway-controller\". \n The format of this - field is DOMAIN \"/\" PATH, where DOMAIN and PATH are - valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." - maxLength: 253 - 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 referent. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - namespace - type: object - required: - - gatewayRef - type: object - maxItems: 100 - type: array - required: - - gateways - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - name: tcproutes.networking.x-k8s.io -spec: - group: networking.x-k8s.io - names: - categories: - - gateway-api - kind: TCPRoute - listKind: TCPRouteList - plural: tcproutes - singular: tcproute - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: TCPRoute is the Schema for the TCPRoute resource. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of TCPRoute. - properties: - gateways: - default: - allow: SameNamespace - description: Gateways defines which Gateways can use this Route. - properties: - allow: - default: SameNamespace - description: 'Allow indicates which Gateways will be allowed to - use this route. Possible values are: * All: Gateways in any - namespace can use this route. * FromList: Only Gateways specified - in GatewayRefs may use this route. * SameNamespace: Only Gateways - in the same namespace may use this route.' - enum: - - All - - FromList - - SameNamespace - type: string - gatewayRefs: - description: GatewayRefs must be specified when Allow is set to - "FromList". In that case, only Gateways referenced in this list - will be allowed to use this route. This field is ignored for - other values of "Allow". - items: - description: GatewayReference identifies a Gateway in a specified - namespace. - properties: - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace is the namespace of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - namespace - type: object - type: array - type: object - rules: - description: Rules are a list of TCP matchers and actions. - items: - description: TCPRouteRule is the configuration for a given rule. - properties: - forwardTo: - description: ForwardTo defines the backend(s) where matching - requests should be sent. - items: - description: RouteForwardTo defines how a Route should forward - a request. - properties: - backendRef: - description: "BackendRef is a reference to a backend to - forward matched requests to. If both BackendRef and - ServiceName are specified, ServiceName will be given - precedence. \n If the referent cannot be found, the - rule is not included in the route. The controller should - raise the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway status - for this route should be updated with a condition that - describes the error more specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - port: - description: "Port specifies the destination port number - to use for the backend referenced by the ServiceName - or BackendRef field. If unspecified, the destination - port in the request is used when forwarding to a backendRef - or serviceName. \n Support: Core" - format: int32 - maximum: 65535 - minimum: 1 - type: integer - serviceName: - description: "ServiceName refers to the name of the Service - to forward matched requests to. When specified, this - takes the place of BackendRef. If both BackendRef and - ServiceName are specified, ServiceName will be given - precedence. \n If the referent cannot be found, the - rule is not included in the route. The controller should - raise the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway status - for this route should be updated with a condition that - describes the error more specifically. \n The protocol - to use is defined using AppProtocol field (introduced - in Kubernetes 1.18) in the Service resource. In the - absence of the AppProtocol field a `networking.x-k8s.io/app-protocol` - annotation on the BackendPolicy resource may be used - to define the protocol. If the AppProtocol field is - available, this annotation should not be used. The AppProtocol - field, when populated, takes precedence over the annotation - in the BackendPolicy resource. For custom backends, - it is encouraged to add a semantically-equivalent field - in the Custom Resource Definition. \n Support: Core" - maxLength: 253 - type: string - weight: - default: 1 - description: "Weight specifies the proportion of HTTP - requests forwarded to the backend referenced by the - ServiceName or BackendRef field. This is computed as - weight/(sum of all weights in this ForwardTo list). - For non-zero values, there may be some epsilon from - the exact proportion defined here depending on the precision - an implementation supports. Weight is not a percentage - and the sum of weights does not need to equal 100. \n - If only one backend is specified and it has a weight - greater than 0, 100% of the traffic is forwarded to - that backend. If weight is set to 0, no traffic should - be forwarded for this entry. If unspecified, weight - defaults to 1. \n Support: Extended" - format: int32 - maximum: 1000000 - minimum: 0 - type: integer - type: object - maxItems: 16 - minItems: 1 - type: array - matches: - description: "Matches define conditions used for matching the - rule against incoming TCP connections. Each match is independent, - i.e. this rule will be matched if **any** one of the matches - is satisfied. If unspecified (i.e. empty), this Rule will - match all requests for the associated Listener. \n Each client - request MUST map to a maximum of one route rule. If a request - matches multiple rules, matching precedence MUST be determined - in order of the following criteria, continuing on ties: \n - * The most specific match specified by ExtensionRef. Each - implementation that supports ExtensionRef may have different - ways of determining the specificity of the referenced extension. - \n If ties still exist across multiple Routes, matching precedence - MUST be determined in order of the following criteria, continuing - on ties: \n * The oldest Route based on creation timestamp. - For example, a Route with a creation timestamp of \"2020-09-08 - 01:02:03\" is given precedence over a Route with a creation - timestamp of \"2020-09-08 01:02:04\". * The Route appearing - first in alphabetical order by \"/\". For - example, foo/bar is given precedence over foo/baz. \n If - ties still exist within the Route that has been given precedence, - matching precedence MUST be granted to the first matching - rule meeting the above criteria." - items: - description: TCPRouteMatch defines the predicate used to match - connections to a given action. - properties: - extensionRef: - description: "ExtensionRef is an optional, implementation-specific - extension to the \"match\" behavior. For example, resource - \"mytcproutematcher\" in group \"networking.acme.io\". - If the referent cannot be found, the rule is not included - in the route. The controller should raise the \"ResolvedRefs\" - condition on the Gateway with the \"DegradedRoutes\" - reason. The gateway status for this route should be - updated with a condition that describes the error more - specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - type: object - maxItems: 8 - type: array - required: - - forwardTo - type: object - maxItems: 16 - minItems: 1 - type: array - required: - - rules - type: object - status: - description: Status defines the current state of TCPRoute. - properties: - gateways: - description: "Gateways is a list of Gateways that are associated with - the route, and the status of the route with respect to each Gateway. - When a Gateway selects this route, the controller that manages the - Gateway must add an entry to this list when the controller first - sees the route and should update the entry as appropriate when the - route is modified. \n A maximum of 100 Gateways will be represented - in this list. If this list is full, there may be additional Gateways - using this Route that are not included in the list. An empty list - means the route has not been admitted by any Gateway." - items: - description: RouteGatewayStatus describes the status of a route - with respect to an associated Gateway. - properties: - conditions: - description: Conditions describes the status of the route with - respect to the Gateway. The "Admitted" condition must always - be specified by controllers to indicate whether the route - has been admitted or rejected by the Gateway, and why. Note - that the route's availability is also subject to the Gateway's - own status conditions and listener status. - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - maxItems: 8 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - gatewayRef: - description: GatewayRef is a reference to a Gateway object that - is associated with the route. - properties: - controller: - description: "Controller is a domain/path string that indicates - the controller implementing the Gateway. This corresponds - with the controller field on GatewayClass. \n Example: - \"acme.io/gateway-controller\". \n The format of this - field is DOMAIN \"/\" PATH, where DOMAIN and PATH are - valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." - maxLength: 253 - 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 referent. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - namespace - type: object - required: - - gatewayRef - type: object - maxItems: 100 - type: array - required: - - gateways - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - name: tlsroutes.networking.x-k8s.io -spec: - group: networking.x-k8s.io - names: - categories: - - gateway-api - kind: TLSRoute - listKind: TLSRouteList - plural: tlsroutes - singular: tlsroute - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: "The TLSRoute resource is similar to TCPRoute, but can be configured - to match against TLS-specific metadata. This allows more flexibility in - matching streams for a given TLS listener. \n If you need to forward traffic - to a single target for a TLS listener, you could choose to use a TCPRoute - with a TLS listener." - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of TLSRoute. - properties: - gateways: - default: - allow: SameNamespace - description: Gateways defines which Gateways can use this Route. - properties: - allow: - default: SameNamespace - description: 'Allow indicates which Gateways will be allowed to - use this route. Possible values are: * All: Gateways in any - namespace can use this route. * FromList: Only Gateways specified - in GatewayRefs may use this route. * SameNamespace: Only Gateways - in the same namespace may use this route.' - enum: - - All - - FromList - - SameNamespace - type: string - gatewayRefs: - description: GatewayRefs must be specified when Allow is set to - "FromList". In that case, only Gateways referenced in this list - will be allowed to use this route. This field is ignored for - other values of "Allow". - items: - description: GatewayReference identifies a Gateway in a specified - namespace. - properties: - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace is the namespace of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - namespace - type: object - type: array - type: object - rules: - description: Rules are a list of TLS matchers and actions. - items: - description: TLSRouteRule is the configuration for a given rule. - properties: - forwardTo: - description: ForwardTo defines the backend(s) where matching - requests should be sent. - items: - description: RouteForwardTo defines how a Route should forward - a request. - properties: - backendRef: - description: "BackendRef is a reference to a backend to - forward matched requests to. If both BackendRef and - ServiceName are specified, ServiceName will be given - precedence. \n If the referent cannot be found, the - rule is not included in the route. The controller should - raise the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway status - for this route should be updated with a condition that - describes the error more specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - port: - description: "Port specifies the destination port number - to use for the backend referenced by the ServiceName - or BackendRef field. If unspecified, the destination - port in the request is used when forwarding to a backendRef - or serviceName. \n Support: Core" - format: int32 - maximum: 65535 - minimum: 1 - type: integer - serviceName: - description: "ServiceName refers to the name of the Service - to forward matched requests to. When specified, this - takes the place of BackendRef. If both BackendRef and - ServiceName are specified, ServiceName will be given - precedence. \n If the referent cannot be found, the - rule is not included in the route. The controller should - raise the \"ResolvedRefs\" condition on the Gateway - with the \"DegradedRoutes\" reason. The gateway status - for this route should be updated with a condition that - describes the error more specifically. \n The protocol - to use is defined using AppProtocol field (introduced - in Kubernetes 1.18) in the Service resource. In the - absence of the AppProtocol field a `networking.x-k8s.io/app-protocol` - annotation on the BackendPolicy resource may be used - to define the protocol. If the AppProtocol field is - available, this annotation should not be used. The AppProtocol - field, when populated, takes precedence over the annotation - in the BackendPolicy resource. For custom backends, - it is encouraged to add a semantically-equivalent field - in the Custom Resource Definition. \n Support: Core" - maxLength: 253 - type: string - weight: - default: 1 - description: "Weight specifies the proportion of HTTP - requests forwarded to the backend referenced by the - ServiceName or BackendRef field. This is computed as - weight/(sum of all weights in this ForwardTo list). - For non-zero values, there may be some epsilon from - the exact proportion defined here depending on the precision - an implementation supports. Weight is not a percentage - and the sum of weights does not need to equal 100. \n - If only one backend is specified and it has a weight - greater than 0, 100% of the traffic is forwarded to - that backend. If weight is set to 0, no traffic should - be forwarded for this entry. If unspecified, weight - defaults to 1. \n Support: Extended" - format: int32 - maximum: 1000000 - minimum: 0 - type: integer - type: object - maxItems: 16 - minItems: 1 - type: array - matches: - description: "Matches define conditions used for matching the - rule against incoming TLS connections. Each match is independent, - i.e. this rule will be matched if **any** one of the matches - is satisfied. If unspecified (i.e. empty), this Rule will - match all requests for the associated Listener. \n Each client - request MUST map to a maximum of one route rule. If a request - matches multiple rules, matching precedence MUST be determined - in order of the following criteria, continuing on ties: \n - * The longest matching SNI. * The longest matching precise - SNI (without a wildcard). This means that \"b.example.com\" - should be given precedence over \"*.example.com\". * The most - specific match specified by ExtensionRef. Each implementation - \ that supports ExtensionRef may have different ways of determining - the specificity of the referenced extension. \n If ties - still exist across multiple Routes, matching precedence MUST - be determined in order of the following criteria, continuing - on ties: \n * The oldest Route based on creation timestamp. - For example, a Route with a creation timestamp of \"2020-09-08 - 01:02:03\" is given precedence over a Route with a creation - timestamp of \"2020-09-08 01:02:04\". * The Route appearing - first in alphabetical order by \"/\". For - example, foo/bar is given precedence over foo/baz. \n If - ties still exist within the Route that has been given precedence, - matching precedence MUST be granted to the first matching - rule meeting the above criteria." - items: - description: TLSRouteMatch defines the predicate used to match - connections to a given action. - properties: - extensionRef: - description: "ExtensionRef is an optional, implementation-specific - extension to the \"match\" behavior. For example, resource - \"mytlsroutematcher\" in group \"networking.acme.io\". - If the referent cannot be found, the rule is not included - in the route. The controller should raise the \"ResolvedRefs\" - condition on the Gateway with the \"DegradedRoutes\" - reason. The gateway status for this route should be - updated with a condition that describes the error more - specifically. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - minLength: 1 - type: string - kind: - description: Kind is kind of the referent. - maxLength: 253 - minLength: 1 - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - snis: - description: "SNIs defines a set of SNI names that should - match against the SNI attribute of TLS ClientHello message - in TLS handshake. \n SNI can be \"precise\" which is - a domain name without the terminating dot of a network - host (e.g. \"foo.example.com\") or \"wildcard\", which - is a domain name prefixed with a single wildcard label - (e.g. `*.example.com`). The wildcard character `*` must - appear by itself as the first DNS label and matches - only a single label. You cannot have a wildcard label - by itself (e.g. Host == `*`). \n Requests will be matched - against the Host field in the following order: \n 1. - If SNI is precise, the request matches this rule if - the SNI in ClientHello is equal to one of the defined - SNIs. 2. If SNI is a wildcard, then the request matches - this rule if the SNI is to equal to the suffix (removing - the first label) of the wildcard rule. 3. If SNIs - is unspecified, all requests associated with the gateway - TLS listener will match. This can be used to define - a default backend for a TLS listener. \n Support: - Core" - items: - description: Hostname is used to specify a hostname - that should be matched. - maxLength: 253 - minLength: 1 - type: string - maxItems: 16 - type: array - type: object - maxItems: 8 - type: array - required: - - forwardTo - type: object - maxItems: 16 - minItems: 1 - type: array - required: - - rules - type: object - status: - description: Status defines the current state of TLSRoute. - properties: - gateways: - description: "Gateways is a list of Gateways that are associated with - the route, and the status of the route with respect to each Gateway. - When a Gateway selects this route, the controller that manages the - Gateway must add an entry to this list when the controller first - sees the route and should update the entry as appropriate when the - route is modified. \n A maximum of 100 Gateways will be represented - in this list. If this list is full, there may be additional Gateways - using this Route that are not included in the list. An empty list - means the route has not been admitted by any Gateway." - items: - description: RouteGatewayStatus describes the status of a route - with respect to an associated Gateway. - properties: - conditions: - description: Conditions describes the status of the route with - respect to the Gateway. The "Admitted" condition must always - be specified by controllers to indicate whether the route - has been admitted or rejected by the Gateway, and why. Note - that the route's availability is also subject to the Gateway's - own status conditions and listener status. - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - maxItems: 8 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - gatewayRef: - description: GatewayRef is a reference to a Gateway object that - is associated with the route. - properties: - controller: - description: "Controller is a domain/path string that indicates - the controller implementing the Gateway. This corresponds - with the controller field on GatewayClass. \n Example: - \"acme.io/gateway-controller\". \n The format of this - field is DOMAIN \"/\" PATH, where DOMAIN and PATH are - valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." - maxLength: 253 - 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 referent. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - namespace - type: object - required: - - gatewayRef - type: object - maxItems: 100 - type: array - required: - - gateways - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/integration/fixtures/k8s/03-gateway.yml b/integration/fixtures/k8s/03-gateway.yml index 2741f0baf..c52f7c166 100644 --- a/integration/fixtures/k8s/03-gateway.yml +++ b/integration/fixtures/k8s/03-gateway.yml @@ -1,41 +1,42 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class listeners: - - protocol: HTTP + - name: http + protocol: HTTP port: 8180 - routes: - kind: HTTPRoute + allowedRoutes: + kinds: + - kind: HTTPRoute --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-tcp-gateway namespace: default spec: gatewayClassName: my-gateway-class listeners: - - protocol: TCP + - name: tcp + protocol: TCP port: 8193 - routes: - kind: TCPRoute - selector: - matchLabels: - app: tcp-app-1 + allowedRoutes: + kinds: + - kind: TCPRoute --- apiVersion: v1 @@ -50,74 +51,67 @@ data: --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-tls-gateway namespace: default spec: gatewayClassName: my-gateway-class listeners: - - protocol: TLS + - name: tls-9001 + protocol: TLS port: 9001 tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute namespaces: from: Same - selector: - matchLabels: - app: tls-app-1 - - protocol: TLS + + - name: tls-9002 + protocol: TLS port: 9002 tls: mode: Terminate - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute - namespaces: - from: Same - selector: - matchLabels: - app: tcp-app-1 + certificateRefs: + - kind: Secret + name: supersecret + allowedRoutes: + kinds: + - kind: TCPRoute --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-https-gateway namespace: default spec: gatewayClassName: my-gateway-class listeners: - - protocol: HTTPS + - name: https + protocol: HTTPS port: 8443 tls: mode: Terminate - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: HTTPRoute - namespaces: - from: Same - selector: - matchLabels: - app: foo + certificateRefs: + - kind: Secret + name: supersecret + allowedRoutes: + kinds: + - kind: HTTPRoute --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + - name: my-https-gateway hostnames: - "foo.com" rules: @@ -125,40 +119,40 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: tcp-app-1 spec: + parentRefs: + - name: my-tcp-gateway + - name: my-tls-gateway rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 8080 weight: 1 --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: tls-app-1 spec: + parentRefs: + - name: my-tls-gateway + hostnames: + - foo.bar rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 8080 weight: 1 - matches: - - snis: - - foo.bar diff --git a/integration/testdata/rawdata-gateway.json b/integration/testdata/rawdata-gateway.json index c5ef16e27..a18a09ef8 100644 --- a/integration/testdata/rawdata-gateway.json +++ b/integration/testdata/rawdata-gateway.json @@ -145,7 +145,7 @@ "entryPoints": [ "footcp" ], - "service": "default-tcp-app-1-my-tcp-gateway-footcp-e3b0c44298fc1c149afb-wrr", + "service": "default-tcp-app-1-my-tcp-gateway-footcp-e3b0c44298fc1c149afb-wrr-0", "rule": "HostSNI(`*`)", "status": "enabled", "using": [ @@ -156,7 +156,7 @@ "entryPoints": [ "footlsterminate" ], - "service": "default-tcp-app-1-my-tls-gateway-footlsterminate-e3b0c44298fc1c149afb-wrr", + "service": "default-tcp-app-1-my-tls-gateway-footlsterminate-e3b0c44298fc1c149afb-wrr-0", "rule": "HostSNI(`*`)", "tls": { "passthrough": false @@ -170,7 +170,7 @@ "entryPoints": [ "footlspassthrough" ], - "service": "default-tls-app-1-my-tls-gateway-footlspassthrough-2279fe75c5156dc5eb26-wrr", + "service": "default-tls-app-1-my-tls-gateway-footlspassthrough-2279fe75c5156dc5eb26-wrr-0", "rule": "HostSNI(`foo.bar`)", "tls": { "passthrough": true @@ -182,7 +182,7 @@ } }, "tcpServices": { - "default-tcp-app-1-my-tcp-gateway-footcp-e3b0c44298fc1c149afb-wrr@kubernetesgateway": { + "default-tcp-app-1-my-tcp-gateway-footcp-e3b0c44298fc1c149afb-wrr-0@kubernetesgateway": { "weighted": { "services": [ { @@ -196,7 +196,7 @@ "default-tcp-app-1-my-tcp-gateway-footcp-e3b0c44298fc1c149afb@kubernetesgateway" ] }, - "default-tcp-app-1-my-tls-gateway-footlsterminate-e3b0c44298fc1c149afb-wrr@kubernetesgateway": { + "default-tcp-app-1-my-tls-gateway-footlsterminate-e3b0c44298fc1c149afb-wrr-0@kubernetesgateway": { "weighted": { "services": [ { @@ -210,7 +210,7 @@ "default-tcp-app-1-my-tls-gateway-footlsterminate-e3b0c44298fc1c149afb@kubernetesgateway" ] }, - "default-tls-app-1-my-tls-gateway-footlspassthrough-2279fe75c5156dc5eb26-wrr@kubernetesgateway": { + "default-tls-app-1-my-tls-gateway-footlspassthrough-2279fe75c5156dc5eb26-wrr-0@kubernetesgateway": { "weighted": { "services": [ { diff --git a/pkg/provider/kubernetes/gateway/client.go b/pkg/provider/kubernetes/gateway/client.go index 6ec6a2e5d..db7715d62 100644 --- a/pkg/provider/kubernetes/gateway/client.go +++ b/pkg/provider/kubernetes/gateway/client.go @@ -16,9 +16,9 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" - "sigs.k8s.io/gateway-api/apis/v1alpha1" - "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned" - "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions" + "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/gateway-api/pkg/client/clientset/gateway/versioned" + "sigs.k8s.io/gateway-api/pkg/client/informers/gateway/externalversions" ) const resyncPeriod = 10 * time.Minute @@ -33,7 +33,7 @@ func (reh *resourceEventHandler) OnAdd(obj interface{}) { func (reh *resourceEventHandler) OnUpdate(oldObj, newObj interface{}) { switch oldObj.(type) { - case *v1alpha1.GatewayClass: + case *v1alpha2.GatewayClass: // Skip update for gateway classes. We only manage addition or deletion for this cluster-wide resource. return default: @@ -51,13 +51,13 @@ func (reh *resourceEventHandler) OnDelete(obj interface{}) { type Client interface { WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error) - GetGatewayClasses() ([]*v1alpha1.GatewayClass, error) - UpdateGatewayStatus(gateway *v1alpha1.Gateway, gatewayStatus v1alpha1.GatewayStatus) error - UpdateGatewayClassStatus(gatewayClass *v1alpha1.GatewayClass, condition metav1.Condition) error - GetGateways() []*v1alpha1.Gateway - GetHTTPRoutes(namespaces []string, selector labels.Selector) ([]*v1alpha1.HTTPRoute, error) - GetTCPRoutes(namespaces []string, selector labels.Selector) ([]*v1alpha1.TCPRoute, error) - GetTLSRoutes(namespaces []string, selector labels.Selector) ([]*v1alpha1.TLSRoute, error) + GetGatewayClasses() ([]*v1alpha2.GatewayClass, error) + UpdateGatewayStatus(gateway *v1alpha2.Gateway, gatewayStatus v1alpha2.GatewayStatus) error + UpdateGatewayClassStatus(gatewayClass *v1alpha2.GatewayClass, condition metav1.Condition) error + GetGateways() []*v1alpha2.Gateway + GetHTTPRoutes(namespaces []string) ([]*v1alpha2.HTTPRoute, error) + GetTCPRoutes(namespaces []string) ([]*v1alpha2.TCPRoute, error) + GetTLSRoutes(namespaces []string) ([]*v1alpha2.TLSRoute, error) GetService(namespace, name string) (*corev1.Service, bool, error) GetSecret(namespace, name string) (*corev1.Secret, bool, error) @@ -177,14 +177,17 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (< c.factoryNamespace.Core().V1().Namespaces().Informer().AddEventHandler(eventHandler) c.factoryGatewayClass = externalversions.NewSharedInformerFactoryWithOptions(c.csGateway, resyncPeriod, externalversions.WithTweakListOptions(labelSelectorOptions)) - c.factoryGatewayClass.Networking().V1alpha1().GatewayClasses().Informer().AddEventHandler(eventHandler) + c.factoryGatewayClass.Gateway().V1alpha2().GatewayClasses().Informer().AddEventHandler(eventHandler) + + // TODO manage Reference Policy + // https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.ReferencePolicy for _, ns := range namespaces { factoryGateway := externalversions.NewSharedInformerFactoryWithOptions(c.csGateway, resyncPeriod, externalversions.WithNamespace(ns)) - factoryGateway.Networking().V1alpha1().Gateways().Informer().AddEventHandler(eventHandler) - factoryGateway.Networking().V1alpha1().HTTPRoutes().Informer().AddEventHandler(eventHandler) - factoryGateway.Networking().V1alpha1().TCPRoutes().Informer().AddEventHandler(eventHandler) - factoryGateway.Networking().V1alpha1().TLSRoutes().Informer().AddEventHandler(eventHandler) + factoryGateway.Gateway().V1alpha2().Gateways().Informer().AddEventHandler(eventHandler) + factoryGateway.Gateway().V1alpha2().HTTPRoutes().Informer().AddEventHandler(eventHandler) + factoryGateway.Gateway().V1alpha2().TCPRoutes().Informer().AddEventHandler(eventHandler) + factoryGateway.Gateway().V1alpha2().TLSRoutes().Informer().AddEventHandler(eventHandler) factoryKube := informers.NewSharedInformerFactoryWithOptions(c.csKube, resyncPeriod, informers.WithNamespace(ns)) factoryKube.Core().V1().Services().Informer().AddEventHandler(eventHandler) @@ -259,21 +262,21 @@ func (c *clientWrapper) GetNamespaces(selector labels.Selector) ([]string, error return namespaces, nil } -func (c *clientWrapper) GetHTTPRoutes(namespaces []string, selector labels.Selector) ([]*v1alpha1.HTTPRoute, error) { - var httpRoutes []*v1alpha1.HTTPRoute +func (c *clientWrapper) GetHTTPRoutes(namespaces []string) ([]*v1alpha2.HTTPRoute, error) { + var httpRoutes []*v1alpha2.HTTPRoute for _, namespace := range namespaces { if !c.isWatchedNamespace(namespace) { - log.WithoutContext().Warnf("Failed to get HTTPRoutes with labels selector %s: %q is not within watched namespaces", selector, namespace) + log.WithoutContext().Warnf("Failed to get HTTPRoutes: %q is not within watched namespaces", namespace) continue } - routes, err := c.factoriesGateway[c.lookupNamespace(namespace)].Networking().V1alpha1().HTTPRoutes().Lister().HTTPRoutes(namespace).List(selector) + routes, err := c.factoriesGateway[c.lookupNamespace(namespace)].Gateway().V1alpha2().HTTPRoutes().Lister().HTTPRoutes(namespace).List(labels.Everything()) if err != nil { return nil, err } if len(routes) == 0 { - log.WithoutContext().Debugf("No HTTPRoutes found in %q namespace with labels selector %s", namespace, selector) + log.WithoutContext().Debugf("No HTTPRoutes found in namespace %q", namespace) continue } @@ -283,21 +286,21 @@ func (c *clientWrapper) GetHTTPRoutes(namespaces []string, selector labels.Selec return httpRoutes, nil } -func (c *clientWrapper) GetTCPRoutes(namespaces []string, selector labels.Selector) ([]*v1alpha1.TCPRoute, error) { - var tcpRoutes []*v1alpha1.TCPRoute +func (c *clientWrapper) GetTCPRoutes(namespaces []string) ([]*v1alpha2.TCPRoute, error) { + var tcpRoutes []*v1alpha2.TCPRoute for _, namespace := range namespaces { if !c.isWatchedNamespace(namespace) { - log.WithoutContext().Warnf("Failed to get TCPRoutes with labels selector %s: %q is not within watched namespaces", selector, namespace) + log.WithoutContext().Warnf("Failed to get TCPRoutes: %q is not within watched namespaces", namespace) continue } - routes, err := c.factoriesGateway[c.lookupNamespace(namespace)].Networking().V1alpha1().TCPRoutes().Lister().TCPRoutes(namespace).List(selector) + routes, err := c.factoriesGateway[c.lookupNamespace(namespace)].Gateway().V1alpha2().TCPRoutes().Lister().TCPRoutes(namespace).List(labels.Everything()) if err != nil { return nil, err } if len(routes) == 0 { - log.WithoutContext().Debugf("No TCPRoutes found in %q namespace with labels selector %s", namespace, selector) + log.WithoutContext().Debugf("No TCPRoutes found in namespace %q", namespace) continue } @@ -306,21 +309,21 @@ func (c *clientWrapper) GetTCPRoutes(namespaces []string, selector labels.Select return tcpRoutes, nil } -func (c *clientWrapper) GetTLSRoutes(namespaces []string, selector labels.Selector) ([]*v1alpha1.TLSRoute, error) { - var tlsRoutes []*v1alpha1.TLSRoute +func (c *clientWrapper) GetTLSRoutes(namespaces []string) ([]*v1alpha2.TLSRoute, error) { + var tlsRoutes []*v1alpha2.TLSRoute for _, namespace := range namespaces { if !c.isWatchedNamespace(namespace) { - log.WithoutContext().Warnf("Failed to get TLSRoutes with labels selector %s: %q is not within watched namespaces", selector, namespace) + log.WithoutContext().Warnf("Failed to get TLSRoutes: %q is not within watched namespaces", namespace) continue } - routes, err := c.factoriesGateway[c.lookupNamespace(namespace)].Networking().V1alpha1().TLSRoutes().Lister().TLSRoutes(namespace).List(selector) + routes, err := c.factoriesGateway[c.lookupNamespace(namespace)].Gateway().V1alpha2().TLSRoutes().Lister().TLSRoutes(namespace).List(labels.Everything()) if err != nil { return nil, err } if len(routes) == 0 { - log.WithoutContext().Debugf("No TLSRoutes found in %q namespace with labels selector %s", namespace, selector) + log.WithoutContext().Debugf("No TLSRoutes found in namespace %q", namespace) continue } @@ -329,11 +332,11 @@ func (c *clientWrapper) GetTLSRoutes(namespaces []string, selector labels.Select return tlsRoutes, nil } -func (c *clientWrapper) GetGateways() []*v1alpha1.Gateway { - var result []*v1alpha1.Gateway +func (c *clientWrapper) GetGateways() []*v1alpha2.Gateway { + var result []*v1alpha2.Gateway for ns, factory := range c.factoriesGateway { - gateways, err := factory.Networking().V1alpha1().Gateways().Lister().List(labels.Everything()) + gateways, err := factory.Gateway().V1alpha2().Gateways().Lister().List(labels.Everything()) if err != nil { log.WithoutContext().Errorf("Failed to list Gateways in namespace %s: %v", ns, err) continue @@ -344,11 +347,11 @@ func (c *clientWrapper) GetGateways() []*v1alpha1.Gateway { return result } -func (c *clientWrapper) GetGatewayClasses() ([]*v1alpha1.GatewayClass, error) { - return c.factoryGatewayClass.Networking().V1alpha1().GatewayClasses().Lister().List(labels.Everything()) +func (c *clientWrapper) GetGatewayClasses() ([]*v1alpha2.GatewayClass, error) { + return c.factoryGatewayClass.Gateway().V1alpha2().GatewayClasses().Lister().List(labels.Everything()) } -func (c *clientWrapper) UpdateGatewayClassStatus(gatewayClass *v1alpha1.GatewayClass, condition metav1.Condition) error { +func (c *clientWrapper) UpdateGatewayClassStatus(gatewayClass *v1alpha2.GatewayClass, condition metav1.Condition) error { gc := gatewayClass.DeepCopy() var newConditions []metav1.Condition @@ -371,7 +374,7 @@ func (c *clientWrapper) UpdateGatewayClassStatus(gatewayClass *v1alpha1.GatewayC ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - _, err := c.csGateway.NetworkingV1alpha1().GatewayClasses().UpdateStatus(ctx, gc, metav1.UpdateOptions{}) + _, err := c.csGateway.GatewayV1alpha2().GatewayClasses().UpdateStatus(ctx, gc, metav1.UpdateOptions{}) if err != nil { return fmt.Errorf("failed to update GatewayClass %q status: %w", gatewayClass.Name, err) } @@ -379,7 +382,7 @@ func (c *clientWrapper) UpdateGatewayClassStatus(gatewayClass *v1alpha1.GatewayC return nil } -func (c *clientWrapper) UpdateGatewayStatus(gateway *v1alpha1.Gateway, gatewayStatus v1alpha1.GatewayStatus) error { +func (c *clientWrapper) UpdateGatewayStatus(gateway *v1alpha2.Gateway, gatewayStatus v1alpha2.GatewayStatus) error { if !c.isWatchedNamespace(gateway.Namespace) { return fmt.Errorf("cannot update Gateway status %s/%s: namespace is not within watched namespaces", gateway.Namespace, gateway.Name) } @@ -394,7 +397,7 @@ func (c *clientWrapper) UpdateGatewayStatus(gateway *v1alpha1.Gateway, gatewaySt ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - _, err := c.csGateway.NetworkingV1alpha1().Gateways(gateway.Namespace).UpdateStatus(ctx, g, metav1.UpdateOptions{}) + _, err := c.csGateway.GatewayV1alpha2().Gateways(gateway.Namespace).UpdateStatus(ctx, g, metav1.UpdateOptions{}) if err != nil { return fmt.Errorf("failed to update Gateway %q status: %w", gateway.Name, err) } @@ -402,7 +405,7 @@ func (c *clientWrapper) UpdateGatewayStatus(gateway *v1alpha1.Gateway, gatewaySt return nil } -func statusEquals(oldStatus, newStatus v1alpha1.GatewayStatus) bool { +func statusEquals(oldStatus, newStatus v1alpha2.GatewayStatus) bool { if len(oldStatus.Listeners) != len(newStatus.Listeners) { return false } @@ -414,7 +417,7 @@ func statusEquals(oldStatus, newStatus v1alpha1.GatewayStatus) bool { listenerMatches := 0 for _, newListener := range newStatus.Listeners { for _, oldListener := range oldStatus.Listeners { - if newListener.Port == oldListener.Port { + if newListener.Name == oldListener.Name { if !conditionsEquals(newListener.Conditions, oldListener.Conditions) { return false } diff --git a/pkg/provider/kubernetes/gateway/client_mock_test.go b/pkg/provider/kubernetes/gateway/client_mock_test.go index df0f7fd97..010ce6635 100644 --- a/pkg/provider/kubernetes/gateway/client_mock_test.go +++ b/pkg/provider/kubernetes/gateway/client_mock_test.go @@ -10,14 +10,14 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes/scheme" - "sigs.k8s.io/gateway-api/apis/v1alpha1" + "sigs.k8s.io/gateway-api/apis/v1alpha2" ) var _ Client = (*clientMock)(nil) func init() { // required by k8s.MustParseYaml - err := v1alpha1.AddToScheme(scheme.Scheme) + err := v1alpha2.AddToScheme(scheme.Scheme) if err != nil { panic(err) } @@ -33,11 +33,11 @@ type clientMock struct { apiSecretError error apiEndpointsError error - gatewayClasses []*v1alpha1.GatewayClass - gateways []*v1alpha1.Gateway - httpRoutes []*v1alpha1.HTTPRoute - tcpRoutes []*v1alpha1.TCPRoute - tlsRoutes []*v1alpha1.TLSRoute + gatewayClasses []*v1alpha2.GatewayClass + gateways []*v1alpha2.Gateway + httpRoutes []*v1alpha2.HTTPRoute + tcpRoutes []*v1alpha2.TCPRoute + tlsRoutes []*v1alpha2.TLSRoute watchChan chan interface{} } @@ -62,15 +62,15 @@ func newClientMock(paths ...string) clientMock { c.namespaces = append(c.namespaces, o) case *corev1.Endpoints: c.endpoints = append(c.endpoints, o) - case *v1alpha1.GatewayClass: + case *v1alpha2.GatewayClass: c.gatewayClasses = append(c.gatewayClasses, o) - case *v1alpha1.Gateway: + case *v1alpha2.Gateway: c.gateways = append(c.gateways, o) - case *v1alpha1.HTTPRoute: + case *v1alpha2.HTTPRoute: c.httpRoutes = append(c.httpRoutes, o) - case *v1alpha1.TCPRoute: + case *v1alpha2.TCPRoute: c.tcpRoutes = append(c.tcpRoutes, o) - case *v1alpha1.TLSRoute: + case *v1alpha2.TLSRoute: c.tlsRoutes = append(c.tlsRoutes, o) default: panic(fmt.Sprintf("Unknown runtime object %+v %T", o, o)) @@ -81,7 +81,7 @@ func newClientMock(paths ...string) clientMock { return c } -func (c clientMock) UpdateGatewayStatus(gateway *v1alpha1.Gateway, gatewayStatus v1alpha1.GatewayStatus) error { +func (c clientMock) UpdateGatewayStatus(gateway *v1alpha2.Gateway, gatewayStatus v1alpha2.GatewayStatus) error { for _, g := range c.gateways { if g.Name == gateway.Name { if !statusEquals(g.Status, gatewayStatus) { @@ -94,7 +94,7 @@ func (c clientMock) UpdateGatewayStatus(gateway *v1alpha1.Gateway, gatewayStatus return nil } -func (c clientMock) UpdateGatewayClassStatus(gatewayClass *v1alpha1.GatewayClass, condition metav1.Condition) error { +func (c clientMock) UpdateGatewayClassStatus(gatewayClass *v1alpha2.GatewayClass, condition metav1.Condition) error { for _, gc := range c.gatewayClasses { if gc.Name == gatewayClass.Name { for _, c := range gc.Status.Conditions { @@ -110,7 +110,7 @@ func (c clientMock) UpdateGatewayClassStatus(gatewayClass *v1alpha1.GatewayClass return nil } -func (c clientMock) UpdateGatewayStatusConditions(gateway *v1alpha1.Gateway, condition metav1.Condition) error { +func (c clientMock) UpdateGatewayStatusConditions(gateway *v1alpha2.Gateway, condition metav1.Condition) error { for _, g := range c.gatewayClasses { if g.Name == gateway.Name { for _, c := range g.Status.Conditions { @@ -126,11 +126,11 @@ func (c clientMock) UpdateGatewayStatusConditions(gateway *v1alpha1.Gateway, con return nil } -func (c clientMock) GetGatewayClasses() ([]*v1alpha1.GatewayClass, error) { +func (c clientMock) GetGatewayClasses() ([]*v1alpha2.GatewayClass, error) { return c.gatewayClasses, nil } -func (c clientMock) GetGateways() []*v1alpha1.Gateway { +func (c clientMock) GetGateways() []*v1alpha2.Gateway { return c.gateways } @@ -148,11 +148,11 @@ func (c clientMock) GetNamespaces(selector labels.Selector) ([]string, error) { return ns, nil } -func (c clientMock) GetHTTPRoutes(namespaces []string, selector labels.Selector) ([]*v1alpha1.HTTPRoute, error) { - var httpRoutes []*v1alpha1.HTTPRoute +func (c clientMock) GetHTTPRoutes(namespaces []string) ([]*v1alpha2.HTTPRoute, error) { + var httpRoutes []*v1alpha2.HTTPRoute for _, namespace := range namespaces { for _, httpRoute := range c.httpRoutes { - if inNamespace(httpRoute.ObjectMeta, namespace) && selector.Matches(labels.Set(httpRoute.Labels)) { + if inNamespace(httpRoute.ObjectMeta, namespace) { httpRoutes = append(httpRoutes, httpRoute) } } @@ -160,11 +160,11 @@ func (c clientMock) GetHTTPRoutes(namespaces []string, selector labels.Selector) return httpRoutes, nil } -func (c clientMock) GetTCPRoutes(namespaces []string, selector labels.Selector) ([]*v1alpha1.TCPRoute, error) { - var tcpRoutes []*v1alpha1.TCPRoute +func (c clientMock) GetTCPRoutes(namespaces []string) ([]*v1alpha2.TCPRoute, error) { + var tcpRoutes []*v1alpha2.TCPRoute for _, namespace := range namespaces { for _, tcpRoute := range c.tcpRoutes { - if inNamespace(tcpRoute.ObjectMeta, namespace) && selector.Matches(labels.Set(tcpRoute.Labels)) { + if inNamespace(tcpRoute.ObjectMeta, namespace) { tcpRoutes = append(tcpRoutes, tcpRoute) } } @@ -172,11 +172,11 @@ func (c clientMock) GetTCPRoutes(namespaces []string, selector labels.Selector) return tcpRoutes, nil } -func (c clientMock) GetTLSRoutes(namespaces []string, selector labels.Selector) ([]*v1alpha1.TLSRoute, error) { - var tlsRoutes []*v1alpha1.TLSRoute +func (c clientMock) GetTLSRoutes(namespaces []string) ([]*v1alpha2.TLSRoute, error) { + var tlsRoutes []*v1alpha2.TLSRoute for _, namespace := range namespaces { for _, tlsRoute := range c.tlsRoutes { - if inNamespace(tlsRoute.ObjectMeta, namespace) && selector.Matches(labels.Set(tlsRoute.Labels)) { + if inNamespace(tlsRoute.ObjectMeta, namespace) { tlsRoutes = append(tlsRoutes, tlsRoute) } } diff --git a/pkg/provider/kubernetes/gateway/client_test.go b/pkg/provider/kubernetes/gateway/client_test.go index 28f6bb14b..f90f7dfae 100644 --- a/pkg/provider/kubernetes/gateway/client_test.go +++ b/pkg/provider/kubernetes/gateway/client_test.go @@ -5,34 +5,34 @@ import ( "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/gateway-api/apis/v1alpha1" + "sigs.k8s.io/gateway-api/apis/v1alpha2" ) func TestStatusEquals(t *testing.T) { testCases := []struct { desc string - statusA v1alpha1.GatewayStatus - statusB v1alpha1.GatewayStatus + statusA v1alpha2.GatewayStatus + statusB v1alpha2.GatewayStatus expected bool }{ { desc: "Empty", - statusA: v1alpha1.GatewayStatus{}, - statusB: v1alpha1.GatewayStatus{}, + statusA: v1alpha2.GatewayStatus{}, + statusB: v1alpha2.GatewayStatus{}, expected: true, }, { desc: "Same status", - statusA: v1alpha1.GatewayStatus{ + statusA: v1alpha2.GatewayStatus{ Conditions: []metav1.Condition{ { Type: "foobar", Reason: "foobar", }, }, - Listeners: []v1alpha1.ListenerStatus{ + Listeners: []v1alpha2.ListenerStatus{ { - Port: 80, + Name: "foo", Conditions: []metav1.Condition{ { Type: "foobar", @@ -42,16 +42,16 @@ func TestStatusEquals(t *testing.T) { }, }, }, - statusB: v1alpha1.GatewayStatus{ + statusB: v1alpha2.GatewayStatus{ Conditions: []metav1.Condition{ { Type: "foobar", Reason: "foobar", }, }, - Listeners: []v1alpha1.ListenerStatus{ + Listeners: []v1alpha2.ListenerStatus{ { - Port: 80, + Name: "foo", Conditions: []metav1.Condition{ { Type: "foobar", @@ -65,11 +65,11 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Listeners length not equal", - statusA: v1alpha1.GatewayStatus{ - Listeners: []v1alpha1.ListenerStatus{}, + statusA: v1alpha2.GatewayStatus{ + Listeners: []v1alpha2.ListenerStatus{}, }, - statusB: v1alpha1.GatewayStatus{ - Listeners: []v1alpha1.ListenerStatus{ + statusB: v1alpha2.GatewayStatus{ + Listeners: []v1alpha2.ListenerStatus{ {}, }, }, @@ -77,10 +77,10 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway conditions length not equal", - statusA: v1alpha1.GatewayStatus{ + statusA: v1alpha2.GatewayStatus{ Conditions: []metav1.Condition{}, }, - statusB: v1alpha1.GatewayStatus{ + statusB: v1alpha2.GatewayStatus{ Conditions: []metav1.Condition{ {}, }, @@ -89,14 +89,14 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway conditions different types", - statusA: v1alpha1.GatewayStatus{ + statusA: v1alpha2.GatewayStatus{ Conditions: []metav1.Condition{ { Type: "foobar", }, }, }, - statusB: v1alpha1.GatewayStatus{ + statusB: v1alpha2.GatewayStatus{ Conditions: []metav1.Condition{ { Type: "foobir", @@ -107,14 +107,14 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway conditions same types but different reason", - statusA: v1alpha1.GatewayStatus{ + statusA: v1alpha2.GatewayStatus{ Conditions: []metav1.Condition{ { Type: "foobar", }, }, }, - statusB: v1alpha1.GatewayStatus{ + statusB: v1alpha2.GatewayStatus{ Conditions: []metav1.Condition{ { Type: "foobar", @@ -126,18 +126,18 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway listeners conditions length", - statusA: v1alpha1.GatewayStatus{ - Listeners: []v1alpha1.ListenerStatus{ + statusA: v1alpha2.GatewayStatus{ + Listeners: []v1alpha2.ListenerStatus{ { - Port: 80, + Name: "foo", Conditions: []metav1.Condition{}, }, }, }, - statusB: v1alpha1.GatewayStatus{ - Listeners: []v1alpha1.ListenerStatus{ + statusB: v1alpha2.GatewayStatus{ + Listeners: []v1alpha2.ListenerStatus{ { - Port: 80, + Name: "foo", Conditions: []metav1.Condition{ {}, }, @@ -148,8 +148,8 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway listeners conditions same types but different status", - statusA: v1alpha1.GatewayStatus{ - Listeners: []v1alpha1.ListenerStatus{ + statusA: v1alpha2.GatewayStatus{ + Listeners: []v1alpha2.ListenerStatus{ { Conditions: []metav1.Condition{ { @@ -159,8 +159,8 @@ func TestStatusEquals(t *testing.T) { }, }, }, - statusB: v1alpha1.GatewayStatus{ - Listeners: []v1alpha1.ListenerStatus{ + statusB: v1alpha2.GatewayStatus{ + Listeners: []v1alpha2.ListenerStatus{ { Conditions: []metav1.Condition{ { @@ -175,8 +175,8 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway listeners conditions same types but different message", - statusA: v1alpha1.GatewayStatus{ - Listeners: []v1alpha1.ListenerStatus{ + statusA: v1alpha2.GatewayStatus{ + Listeners: []v1alpha2.ListenerStatus{ { Conditions: []metav1.Condition{ { @@ -186,8 +186,8 @@ func TestStatusEquals(t *testing.T) { }, }, }, - statusB: v1alpha1.GatewayStatus{ - Listeners: []v1alpha1.ListenerStatus{ + statusB: v1alpha2.GatewayStatus{ + Listeners: []v1alpha2.ListenerStatus{ { Conditions: []metav1.Condition{ { @@ -201,11 +201,11 @@ func TestStatusEquals(t *testing.T) { expected: false, }, { - desc: "Gateway listeners conditions same types/reason but different ports", - statusA: v1alpha1.GatewayStatus{ - Listeners: []v1alpha1.ListenerStatus{ + desc: "Gateway listeners conditions same types/reason but different names", + statusA: v1alpha2.GatewayStatus{ + Listeners: []v1alpha2.ListenerStatus{ { - Port: 80, + Name: "foo", Conditions: []metav1.Condition{ { Type: "foobar", @@ -215,10 +215,10 @@ func TestStatusEquals(t *testing.T) { }, }, }, - statusB: v1alpha1.GatewayStatus{ - Listeners: []v1alpha1.ListenerStatus{ + statusB: v1alpha2.GatewayStatus{ + Listeners: []v1alpha2.ListenerStatus{ { - Port: 443, + Name: "bar", Conditions: []metav1.Condition{ { Type: "foobar", diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/gatewayclass_with_unknown_controller.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/gatewayclass_with_unknown_controller.yml index d380ec774..b7982b94d 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/gatewayclass_with_unknown_controller.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/gatewayclass_with_unknown_controller.yml @@ -1,38 +1,33 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: unkown.io/gateway-controller + controllerName: unkown.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: hostnames: - "foo.com" @@ -41,7 +36,7 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/one_rule_two_targets.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/one_rule_two_targets.yml index 6d847a175..bd181b220 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/one_rule_two_targets.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/one_rule_two_targets.yml @@ -1,39 +1,38 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -41,10 +40,14 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 - - serviceName: whoami2 + kind: Service + group: "" + - name: whoami2 port: 8080 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple.yml index c3116d2f5..f48efddf2 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple.yml @@ -1,39 +1,41 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -41,7 +43,9 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_cross_provider.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_cross_provider.yml index 9494c0ba5..3010f3a59 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_cross_provider.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_cross_provider.yml @@ -1,39 +1,38 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -41,13 +40,15 @@ spec: - path: type: Exact value: /bar - forwardTo: + backendRefs: - weight: 1 - backendRef: - group: traefik.containo.us - kind: TraefikService - name: service@file + group: traefik.containo.us + kind: TraefikService + name: service@file port: 80 - - serviceName: whoami + + - name: whoami port: 80 weight: 1 + group: "" + kind: Service diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_to_api_internal.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_to_api_internal.yml index 50bfc0bc6..6fe6d48b6 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_to_api_internal.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_to_api_internal.yml @@ -1,39 +1,38 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -41,10 +40,9 @@ spec: - path: type: Exact value: /bar - forwardTo: + backendRefs: - weight: 1 - backendRef: - group: traefik.containo.us - kind: TraefikService - name: api@internal + group: traefik.containo.us + kind: TraefikService + name: api@internal port: 80 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_bad_rule.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_bad_rule.yml index 2c7cf375e..0ce0690e3 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_bad_rule.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_bad_rule.yml @@ -1,47 +1,46 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: - matches: - path: - type: ImplementationSpecific + type: PathPrefix value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_tls_entrypoint.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_tls_entrypoint.yml index 5d9cad308..ca1f133c3 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_tls_entrypoint.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_tls_entrypoint.yml @@ -1,39 +1,38 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 443 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -41,7 +40,7 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/two_rules.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/two_rules.yml index f2b2b10f4..cc4ee179f 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/two_rules.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/two_rules.yml @@ -1,39 +1,38 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -41,15 +40,19 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" - matches: - path: type: Exact value: /bir - forwardTo: - - serviceName: whoami2 + backendRefs: + - name: whoami2 port: 8080 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_host.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_host.yml index 91cc07280..34e676f55 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_host.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_host.yml @@ -1,44 +1,45 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" - "bar.com" rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_all.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_all.yml index 6257471a4..d40ab73ca 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_all.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_all.yml @@ -1,39 +1,38 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: All - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-default namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -41,20 +40,25 @@ spec: - path: type: Exact value: /foo - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-bar namespace: bar - labels: - app: foo spec: + parentRefs: + - name: my-gateway + namespace: default + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "bar.com" rules: @@ -62,7 +66,9 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami-bar + backendRefs: + - name: whoami-bar port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_same.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_same.yml index e9b10719d..aa793a556 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_same.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_same.yml @@ -1,39 +1,38 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-default namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -41,19 +40,19 @@ spec: - path: type: Exact value: /foo - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-bar namespace: bar - labels: - app: foo spec: hostnames: - "bar.com" @@ -62,7 +61,9 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami-bar + backendRefs: + - name: whoami-bar port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_selector.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_selector.yml index cdff9a276..a5bffb47a 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_selector.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_selector.yml @@ -8,43 +8,42 @@ metadata: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Selector selector: matchLabels: foo: bar - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-default namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -52,20 +51,25 @@ spec: - path: type: Exact value: /foo - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-bar namespace: bar - labels: - app: foo spec: + parentRefs: + - name: my-gateway + namespace: default + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "bar.com" rules: @@ -73,7 +77,9 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami-bar + backendRefs: + - name: whoami-bar port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https.yml index 8262a65d3..9512aae07 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https.yml @@ -11,45 +11,44 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTPS + listeners: # Use GatewayClass defaults for listener definition. + - name: https + protocol: HTTPS port: 443 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: HTTPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -57,7 +56,9 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_with_tls_passthrough.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_with_tls_passthrough.yml index 93c611d59..e104514e0 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_with_tls_passthrough.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_with_tls_passthrough.yml @@ -11,45 +11,39 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTPS + listeners: # Use GatewayClass defaults for listener definition. + - name: https + protocol: HTTPS port: 443 tls: mode: Passthrough - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: HTTPRoute + certificateRefs: + - kind: Secret + name: supersecret + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: hostnames: - "foo.com" @@ -58,7 +52,7 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_without_tls.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_without_tls.yml index 9968576ae..09c74b40d 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_without_tls.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_without_tls.yml @@ -1,38 +1,33 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTPS + listeners: # Use GatewayClass defaults for listener definition. + - name: https + protocol: HTTPS port: 443 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: hostnames: - "foo.com" @@ -41,7 +36,7 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tcp.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tcp.yml index 17d31657b..02ca3936d 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tcp.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tcp.yml @@ -1,38 +1,33 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp + protocol: TCP port: 443 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: hostnames: - "foo.com" @@ -41,7 +36,7 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tls.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tls.yml index 97213a151..9733a895c 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tls.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tls.yml @@ -11,45 +11,39 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 443 tls: mode: Terminate - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: HTTPRoute + certificateRefs: + - kind: Secret + name: supersecret + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: hostnames: - "foo.com" @@ -58,7 +52,7 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_several_rules.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_several_rules.yml index 7821d2b74..aeea3c26b 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_several_rules.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_several_rules.yml @@ -1,65 +1,70 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: - matches: - path: - type: Prefix + type: PathPrefix value: /bar headers: - type: Exact - values: - my-header: foo - my-header2: bar - forwardTo: - - serviceName: whoami + - name: my-header + type: Exact + value: foo + - name: my-header2 + type: Exact + value: bar + backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" - matches: - path: type: Exact value: /bar headers: - type: Exact - values: - my-header: bar - forwardTo: - - serviceName: whoami + - name: my-header + type: Exact + value: bar + backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_tls_configuration.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_tls_configuration.yml new file mode 100644 index 000000000..81362d6d6 --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_tls_configuration.yml @@ -0,0 +1,24 @@ +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway-class +spec: + controllerName: traefik.io/gateway-controller + +--- +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway + namespace: default +spec: + gatewayClassName: my-gateway-class + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP + port: 80 + tls: { } + allowedRoutes: + namespaces: + from: Same diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_gateways_one_httproute.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_gateways_one_httproute.yml index 1a1ee1253..ceb9f2061 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_gateways_one_httproute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_gateways_one_httproute.yml @@ -11,64 +11,63 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-https namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTPS + listeners: # Use GatewayClass defaults for listener definition. + - name: https + protocol: HTTPS port: 443 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: HTTPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-http namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway-http + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway-https + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -76,7 +75,9 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_listeners_one_httproute.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_listeners_one_httproute.yml index 928d77d27..7bd9fd05e 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_listeners_one_httproute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_listeners_one_httproute.yml @@ -11,54 +11,51 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTPS + listeners: # Use GatewayClass defaults for listener definition. + - name: https + protocol: HTTPS port: 443 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: HTTPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo - - protocol: HTTP + + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -66,7 +63,9 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_wrong_service_port.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_wrong_service_port.yml index 43fbaa501..e5959a809 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_wrong_service_port.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_wrong_service_port.yml @@ -1,39 +1,38 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" rules: @@ -41,7 +40,7 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami weight: 1 port: 9000 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/without_gatewayclass.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/without_gatewayclass.yml index d585d7f2c..be795970a 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/without_gatewayclass.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/without_gatewayclass.yml @@ -1,30 +1,25 @@ --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: hostnames: - "foo.com" @@ -33,7 +28,7 @@ spec: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoami + backendRefs: + - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/without_httproute.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/without_httproute.yml index 2bbc734b1..228525d55 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/without_httproute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/without_httproute.yml @@ -1,26 +1,20 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute - namespaces: - from: Same - selector: - matchLabels: - app: foo diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/simple.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/simple.yml index 5906c05eb..60f77deb4 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/simple.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/simple.yml @@ -11,122 +11,149 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 9080 - routes: - kind: HTTPRoute + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: http-app - - protocol: HTTPS + + - name: https + protocol: HTTPS port: 9443 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: HTTPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: http-app - - protocol: TCP + + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tcp-app - - protocol: TLS + + - name: tls-10000 + protocol: TLS port: 10000 hostname: tls.foo.example.com tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tcp-app - - protocol: TLS + + - name: tls-11000 + protocol: TLS port: 11000 hostname: pass.tls.foo.example.com tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tls-app --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: http-app spec: + parentRefs: + - name: my-gateway + sectionName: http + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + sectionName: https + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: tcp-app spec: + parentRefs: + - name: my-gateway + sectionName: tcp + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + sectionName: tls-10000 + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + sectionName: tls-11000 + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_protocol.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_protocol.yml index b42d857c5..f6519d8ea 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_protocol.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_protocol.yml @@ -1,41 +1,41 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class listeners: - - protocol: UNKNOWN + - name: unknown + protocol: UNKNOWN port: 9080 - routes: - kind: HTTPRoute + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: http-app --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: http-app spec: rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_route_kind.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_route_kind.yml index be61af4e1..3df51b8a4 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_route_kind.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_route_kind.yml @@ -1,41 +1,41 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class listeners: - - protocol: HTTP + - name: http + protocol: HTTP port: 9080 - routes: - kind: UnknownRoute + allowedRoutes: + kinds: + - kind: UnknownRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: http-app --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: http-app spec: rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_core_group.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_core_group.yml new file mode 100644 index 000000000..88047e8e1 --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_core_group.yml @@ -0,0 +1,135 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: supersecret + namespace: default + +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= + +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway-class +spec: + controllerName: traefik.io/gateway-controller + +--- +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway + namespace: default +spec: + gatewayClassName: my-gateway-class + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP + port: 9080 + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + + - name: https + protocol: HTTPS + port: 9443 + tls: + certificateRefs: + - kind: Secret + name: supersecret + group: "core" + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + + - name: tcp + protocol: TCP + port: 9000 + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + + - name: tls + protocol: TLS + port: 10000 + hostname: tls.foo.example.com + tls: + certificateRefs: + - kind: Secret + name: supersecret + group: "core" + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + +--- +kind: HTTPRoute +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: http-app-default + namespace: default +spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + rules: + - backendRefs: + - name: whoami + port: 80 + weight: 1 + kind: Service + group: core + +--- +kind: TCPRoute +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: tcp-app-default + namespace: default +spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + rules: + - backendRefs: + - name: whoamitcp + port: 9000 + weight: 1 + kind: Service + group: core + +--- +kind: TLSRoute +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: tls-app-default + namespace: default +spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + rules: + - backendRefs: + - name: whoamitcp + port: 9000 + weight: 1 + kind: Service + group: core diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_incompatible_protocol_and_route_kind.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_incompatible_protocol_and_route_kind.yml index 16467833b..c4a146881 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_incompatible_protocol_and_route_kind.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_incompatible_protocol_and_route_kind.yml @@ -1,41 +1,41 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class listeners: - - protocol: TLS + - name: tls + protocol: TLS port: 9080 - routes: - kind: HTTPRoute + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: http-app --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: http-app spec: rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_multiple_protocol_using_same_port.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_multiple_protocol_using_same_port.yml index fa45fe0f3..448dec2c7 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_multiple_protocol_using_same_port.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_multiple_protocol_using_same_port.yml @@ -11,130 +11,130 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http1 + protocol: HTTP port: 9080 - routes: - kind: HTTPRoute + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: http-app-1 - - protocol: HTTP + + - name: http2 + protocol: HTTP port: 9080 - routes: - kind: HTTPRoute + allowedRoutes: + kinds: + - kind: HTTPRoute namespaces: from: Same - selector: - matchLabels: - app: http-app-2 - - protocol: TCP + + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute + allowedRoutes: + kinds: + - kind: TCPRoute namespaces: from: Same - selector: - matchLabels: - app: tcp-app - - protocol: TLS + + - name: tls + protocol: TLS port: 9000 tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute namespaces: from: Same - selector: - matchLabels: - app: tls-app - - protocol: TLS + + - name: tls2 + protocol: TLS port: 9000 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: TCPRoute namespaces: from: Same - selector: - matchLabels: - app: tcp-app --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: http-app spec: rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-2 namespace: default - labels: - app: http-app spec: rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: tcp-app spec: rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: tls-app spec: rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_all.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_all.yml index 493700124..f12dad908 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_all.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_all.yml @@ -11,167 +11,222 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 9080 - routes: - kind: HTTPRoute + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io namespaces: from: All - selector: - matchLabels: - app: http-app - - protocol: HTTPS + + - name: https + protocol: HTTPS port: 9443 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: HTTPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io namespaces: from: All - selector: - matchLabels: - app: http-app - - protocol: TCP + + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: All - selector: - matchLabels: - app: tcp-app - - protocol: TLS + + - name: tls-10000 + protocol: TLS port: 10000 hostname: tls.foo.example.com tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: All - selector: - matchLabels: - app: tcp-app - - protocol: TLS + + - name: tls-11000 + protocol: TLS port: 11000 hostname: pass.tls.foo.example.com tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tls-app --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-default namespace: default - labels: - app: http-app spec: + parentRefs: + - name: my-gateway + sectionName: http + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + sectionName: https + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-default namespace: default - labels: - app: tcp-app spec: + parentRefs: + - name: my-gateway + sectionName: tcp + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + sectionName: tls-10000 + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-default namespace: default - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + sectionName: tls-11000 + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-bar namespace: bar - labels: - app: http-app spec: + parentRefs: + - name: my-gateway + namespace: default + sectionName: http + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + namespace: default + sectionName: https + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoami-bar + - backendRefs: + - name: whoami-bar port: 80 weight: 1 + kind: Service + group: "" --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-bar namespace: bar - labels: - app: tcp-app spec: + parentRefs: + - name: my-gateway + namespace: default + sectionName: tcp + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + namespace: default + sectionName: tls-10000 + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp-bar + - backendRefs: + - name: whoamitcp-bar port: 9000 weight: 1 + kind: Service + group: "" --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-bar namespace: bar - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + namespace: default + sectionName: tls-11000 + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp-bar + - backendRefs: + - name: whoamitcp-bar port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_same.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_same.yml index e75c052e7..4dbf7118c 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_same.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_same.yml @@ -11,167 +11,222 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 9080 - routes: - kind: HTTPRoute + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: http-app - - protocol: HTTPS + + - name: https + protocol: HTTPS port: 9443 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: HTTPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: http-app - - protocol: TCP + + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tcp-app - - protocol: TLS + + - name: tls + protocol: TLS port: 10000 hostname: tls.foo.example.com tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tcp-app - - protocol: TLS + + - name: tls2 + protocol: TLS port: 11000 hostname: pass.tls.foo.example.com tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tls-app --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-default namespace: default - labels: - app: http-app spec: + parentRefs: + - name: my-gateway + sectionName: http + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + sectionName: https + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-default namespace: default - labels: - app: tcp-app spec: + parentRefs: + - name: my-gateway + sectionName: tcp + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + sectionName: tls + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-default namespace: default - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + sectionName: tls2 + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-bar namespace: bar - labels: - app: http-app spec: + parentRefs: + - name: my-gateway + namespace: default + sectionName: http + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + namespace: default + sectionName: https + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoami-bar + - backendRefs: + - name: whoami-bar port: 80 weight: 1 + kind: Service + group: "" --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-bar namespace: bar - labels: - app: tcp-app spec: + parentRefs: + - name: my-gateway + namespace: default + sectionName: tcp + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + namespace: default + sectionName: tls + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp-bar + - backendRefs: + - name: whoamitcp-bar port: 9000 weight: 1 + kind: Service + group: "" --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-bar namespace: bar - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + namespace: default + sectionName: tls2 + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp-bar + - backendRefs: + - name: whoamitcp-bar port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_selector.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_selector.yml index 3d9e0aff8..e2c982eaa 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_selector.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_selector.yml @@ -17,185 +17,250 @@ data: tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= +--- +apiVersion: v1 +kind: Secret +metadata: + name: supersecret + namespace: default + +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= + --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 9080 - routes: - kind: HTTPRoute + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io namespaces: from: Selector selector: matchLabels: foo: bar - selector: - matchLabels: - app: http-app - - protocol: HTTPS + + - name: https + protocol: HTTPS port: 9443 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: HTTPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io namespaces: from: Selector selector: matchLabels: foo: bar - selector: - matchLabels: - app: http-app - - protocol: TCP + + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Selector selector: matchLabels: foo: bar - selector: - matchLabels: - app: tcp-app - - protocol: TLS + + - name: tls + protocol: TLS port: 10000 hostname: tls.foo.example.com tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Selector selector: matchLabels: foo: bar - selector: - matchLabels: - app: tcp-app - - protocol: TLS + + - name: tls2 + protocol: TLS port: 11000 hostname: pass.tls.foo.example.com tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: Selector selector: matchLabels: foo: bar - selector: - matchLabels: - app: tls-app --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-default namespace: default - labels: - app: http-app spec: + parentRefs: + - name: my-gateway + sectionName: http + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + sectionName: https + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-default namespace: default - labels: - app: tcp-app spec: + parentRefs: + - name: my-gateway + sectionName: tcp + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + sectionName: tls + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-default namespace: default - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + sectionName: tls2 + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-bar namespace: bar - labels: - app: http-app spec: + parentRefs: + - name: my-gateway + namespace: default + sectionName: http + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + namespace: default + sectionName: https + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoami-bar + - backendRefs: + - name: whoami-bar port: 80 weight: 1 + kind: Service + group: "" --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-bar namespace: bar - labels: - app: tcp-app spec: + parentRefs: + - name: my-gateway + namespace: default + sectionName: tcp + kind: Gateway + group: gateway.networking.k8s.io + - name: my-gateway + namespace: default + sectionName: tls + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp-bar + - backendRefs: + - name: whoamitcp-bar port: 9000 weight: 1 + kind: Service + group: "" --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-bar namespace: bar - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + namespace: default + sectionName: tls2 + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp-bar + - backendRefs: + - name: whoamitcp-bar port: 9000 weight: 1 - + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_wrong_routes_selector.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_wrong_routes_selector.yml index 93f0661c1..4562ecfe4 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_wrong_routes_selector.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_wrong_routes_selector.yml @@ -1,75 +1,99 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class namespace: default spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-mixed-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute - selector: - matchLabels: - app: label-tls-app-1 - - protocol: TCP + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute - selector: - matchLabels: - app: label-tls-app-1 - - protocol: TLS + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + + - name: tls + protocol: TLS port: 9443 tls: mode: Passthrough - routes: - kind: TLSRoute - selector: - matchLabels: - app: label-http-app-1 + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io + namespaces: + from: Same --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: label-tls-app-1 spec: + parentRefs: + - name: my-mixed-gateway + sectionName: http + kind: Gateway + group: gateway.networking.k8s.io + - name: my-mixed-gateway + sectionName: tcp + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default labels: app: label-http-app-1 spec: + parentRefs: + - name: my-mixed-gateway + sectionName: tls + kind: Gateway + group: gateway.networking.k8s.io rules: - matches: - path: type: Exact value: /bar - forwardTo: - - serviceName: whoamitcp + backendRefs: + - name: whoamitcp port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/gatewayclass_with_unknown_controller.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/gatewayclass_with_unknown_controller.yml index df4658917..e7bf59d20 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/gatewayclass_with_unknown_controller.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/gatewayclass_with_unknown_controller.yml @@ -1,41 +1,41 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: unkown.io/gateway-controller + controllerName: unkown.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp + protocol: TCP port: 8080 - routes: - kind: TCPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: TCP-app-1 namespace: default - labels: - app: foo spec: rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple.yml index bde9383db..49e6fb1d4 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple.yml @@ -1,40 +1,46 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class namespace: default spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-tcp-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute - selector: - matchLabels: - app: whoamitcp + allowedRoutes: + namespaces: + from: Same + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: whoamitcp spec: + parentRefs: + - name: my-tcp-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_cross_provider.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_cross_provider.yml index 264599220..a712ca739 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_cross_provider.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_cross_provider.yml @@ -1,47 +1,50 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tcp-app --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: tcp-app spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: + - backendRefs: - weight: 1 - backendRef: - group: traefik.containo.us - kind: TraefikService - name: service@file + group: traefik.containo.us + kind: TraefikService + name: service@file port: 9000 - - serviceName: whoamitcp + - name: whoamitcp port: 9000 weight: 1 + group: "" + kind: Service diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_routes.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_routes.yml index 863b37c10..d4da7c2fc 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_routes.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_routes.yml @@ -1,62 +1,77 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class namespace: default spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-tcp-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp-app-1 + protocol: TCP port: 9000 - routes: - kind: TCPRoute - selector: - matchLabels: - app: label-tcp-app-1 - - protocol: TCP + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + + - name: tcp-app-2 + protocol: TCP port: 10000 - routes: - kind: TCPRoute - selector: - matchLabels: - app: label-tcp-app-2 + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: label-tcp-app-1 spec: + parentRefs: + - name: my-tcp-gateway + sectionName: tcp-app-1 + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-2 namespace: default - labels: - app: label-tcp-app-2 spec: + parentRefs: + - name: my-tcp-gateway + sectionName: tcp-app-2 + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 10000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_rules.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_rules.yml index ea8a95ed9..57496b0d6 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_rules.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_rules.yml @@ -1,44 +1,52 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class namespace: default spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-tcp-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute - selector: - matchLabels: - app: label-tcp-app + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app namespace: default - labels: - app: label-tcp-app spec: + parentRefs: + - name: my-tcp-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 - - forwardTo: - - serviceName: whoamitcp + kind: Service + group: "" + - backendRefs: + - name: whoamitcp port: 10000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_all.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_all.yml index 07d498fb4..27c9abce6 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_all.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_all.yml @@ -1,57 +1,66 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class namespace: default spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-tcp-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: - from: All - selector: - matchLabels: - app: whoamitcp + from: All --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-default namespace: default - labels: - app: whoamitcp spec: + parentRefs: + - name: my-tcp-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-bar namespace: bar - labels: - app: whoamitcp spec: + parentRefs: + - name: my-tcp-gateway + namespace: default + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp-bar + - backendRefs: + - name: whoamitcp-bar port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_same.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_same.yml index 02eedf059..43e251edd 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_same.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_same.yml @@ -1,57 +1,66 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class namespace: default spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-tcp-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: - from: Same - selector: - matchLabels: - app: whoamitcp + from: Same --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-default namespace: default - labels: - app: whoamitcp spec: + parentRefs: + - name: my-tcp-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-bar namespace: bar - labels: - app: whoamitcp spec: + parentRefs: + - name: my-tcp-gateway + namespace: default + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp-bar + - backendRefs: + - name: whoamitcp-bar port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_selector.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_selector.yml index 39e3aa214..94c7770c9 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_selector.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_selector.yml @@ -8,61 +8,70 @@ metadata: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class namespace: default spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-tcp-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp + protocol: TCP port: 9000 - routes: - kind: TCPRoute + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Selector selector: matchLabels: foo: bar - selector: - matchLabels: - app: whoamitcp --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-default namespace: default - labels: - app: whoamitcp spec: + parentRefs: + - name: my-tcp-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-bar namespace: bar - labels: - app: whoamitcp spec: + parentRefs: + - name: my-tcp-gateway + namespace: default + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp-bar + - backendRefs: + - name: whoamitcp-bar port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_http.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_http.yml index 8f70a67a7..724103c4a 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_http.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_http.yml @@ -1,42 +1,37 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 9000 hostname: foo.example.com - routes: - kind: TCPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: tcp-app --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: tcp-app spec: rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_https.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_https.yml index f19ded9c4..b207e758c 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_https.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_https.yml @@ -11,49 +11,43 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTPS + listeners: # Use GatewayClass defaults for listener definition. + - name: https + protocol: HTTPS port: 9000 hostname: foo.example.com tls: mode: Terminate # Default mode - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute + certificateRefs: + - kind: Secret + name: supersecret + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: tcp-app --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: tcp-app spec: rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_tls.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_tls.yml index b43f91575..6d4228279 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_tls.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_tls.yml @@ -11,49 +11,53 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 9000 hostname: foo.example.com tls: mode: Terminate # Default mode - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tcp-app --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: tcp-app spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_tls_configuration.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_tls_configuration.yml new file mode 100644 index 000000000..d31ddeb04 --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_tls_configuration.yml @@ -0,0 +1,26 @@ +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway-class +spec: + controllerName: traefik.io/gateway-controller + +--- +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway + namespace: default +spec: + gatewayClassName: my-gateway-class + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: TCP + port: 8080 + tls: { } + allowedRoutes: + namespaces: + from: Same + kinds: + - kind: TCPRoute diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_wrong_service_port.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_wrong_service_port.yml index 88fd5793a..7c442a179 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_wrong_service_port.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_wrong_service_port.yml @@ -1,41 +1,41 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: TCP port: 8080 - routes: - kind: TCPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: TCP-app-1 namespace: default - labels: - app: foo spec: rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami weight: 1 port: 9000 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_gatewayclass.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_gatewayclass.yml index 5c8eef5f2..231e6e55d 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_gatewayclass.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_gatewayclass.yml @@ -1,33 +1,33 @@ --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp + protocol: TCP port: 8080 - routes: - kind: TCPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: TCP-app-1 namespace: default - labels: - app: foo spec: rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute.yml index 53d84d6af..64eb3c73b 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute.yml @@ -1,26 +1,26 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp + protocol: TCP port: 8080 - routes: - kind: TCPRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute_tls_protocol.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute_tls_protocol.yml index 03ee5a759..d6c6fa309 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute_tls_protocol.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute_tls_protocol.yml @@ -11,33 +11,29 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 8080 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: foo - diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/gatewayclass_with_unknown_controller.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/gatewayclass_with_unknown_controller.yml index f92d5b608..76fa7680f 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/gatewayclass_with_unknown_controller.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/gatewayclass_with_unknown_controller.yml @@ -11,47 +11,47 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: unkown.io/gateway-controller + controllerName: unkown.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS tls: - certificateRef: - kind: Secret - name: supersecret - group: core + certificateRefs: + - kind: Secret + name: supersecret + group: "" port: 8080 - routes: - kind: TCPRoute + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: foo spec: rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute.yml index 2aff54e94..25c935451 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute.yml @@ -11,47 +11,53 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class namespace: default spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-tls-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS hostname: foo.example.com port: 9000 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute - selector: - matchLabels: - app: whoamitcp + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: whoamitcp spec: + parentRefs: + - name: my-tls-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute_passthrough.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute_passthrough.yml new file mode 100644 index 000000000..525d6dbf2 --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute_passthrough.yml @@ -0,0 +1,49 @@ +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway-class + namespace: default +spec: + controllerName: traefik.io/gateway-controller + +--- +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-tls-gateway + namespace: default +spec: + gatewayClassName: my-gateway-class + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS + hostname: foo.example.com + port: 9000 + tls: + mode: Passthrough + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + +--- +kind: TCPRoute +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: tcp-app-1 + namespace: default +spec: + parentRefs: + - name: my-tls-gateway + kind: Gateway + group: gateway.networking.k8s.io + rules: + - backendRefs: + - name: whoamitcp + port: 9000 + weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute_with_certificateRef.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute_with_certificateRef.yml deleted file mode 100644 index b9f4e6c28..000000000 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute_with_certificateRef.yml +++ /dev/null @@ -1,57 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - name: supersecret - namespace: default - -data: - tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= - tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= - ---- -kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 -metadata: - name: my-gateway-class - namespace: default -spec: - controller: traefik.io/gateway-controller - ---- -kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 -metadata: - name: my-tls-gateway - namespace: default -spec: - gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS - hostname: foo.example.com - port: 9000 - tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TLSRoute - selector: - matchLabels: - app: whoamitls - ---- -kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 -metadata: - name: tls-app-1 - namespace: default - labels: - app: whoamitls -spec: - rules: - - forwardTo: - - serviceName: whoamitcp - port: 9000 - weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TLSRoute.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TLSRoute.yml index 37fd4de2b..de79b72a0 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TLSRoute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TLSRoute.yml @@ -11,44 +11,50 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class namespace: default spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-tls-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS hostname: foo.example.com port: 9000 tls: mode: Passthrough - routes: - kind: TLSRoute - selector: - matchLabels: - app: whoamitcp + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io + namespaces: + from: Same --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: whoamitcp spec: + parentRefs: + - name: my-tls-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_cross_provider.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_cross_provider.yml index 9a230285e..d530c3d0e 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_cross_provider.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_cross_provider.yml @@ -11,53 +11,56 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 9000 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tcp-app --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: tcp-app spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: + - backendRefs: - weight: 1 - backendRef: - group: traefik.containo.us - kind: TraefikService - name: service@file + group: traefik.containo.us + kind: TraefikService + name: service@file port: 9000 - - serviceName: whoamitcp + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_SNI_matching.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_SNI_matching.yml index ffc3c459b..f4f09af5f 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_SNI_matching.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_SNI_matching.yml @@ -1,48 +1,50 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 9001 - hostname: foo.example.com + hostname: "*.example.com" tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tls-app --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - foo.example.com rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 - matches: - - snis: - - foo.bar - + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_invalid_SNI_matching.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_invalid_SNI_matching.yml index 8a8a55a50..004e1a4b9 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_invalid_SNI_matching.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_invalid_SNI_matching.yml @@ -1,49 +1,49 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 9001 - hostname: foo.example.com tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tls-app --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - "*.foo.bar" rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 - matches: - - snis: - - foo.bar - - "*" - + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_SNI_matching.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_SNI_matching.yml index ced8e2288..ae03dc627 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_SNI_matching.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_SNI_matching.yml @@ -1,49 +1,51 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 9001 - hostname: foo.example.com + hostname: "*.example.com" tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tls-app --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - foo.example.com + - bar.example.com rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 - matches: - - snis: - - foo.bar - - fiz.baz - + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_routes_kind.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_routes_kind.yml index 8d665c11e..2f62394e4 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_routes_kind.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_routes_kind.yml @@ -11,71 +11,84 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class namespace: default spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-tls-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls-9000 + protocol: TLS hostname: foo.example.com port: 9000 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute - selector: - matchLabels: - app: label-tcp-app-1 - - protocol: TLS + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + + - name: tls-10000 + protocol: TLS port: 10000 tls: mode: Passthrough - routes: - kind: TLSRoute - selector: - matchLabels: - app: label-tls-app-1 + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io + namespaces: + from: Same --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: label-tcp-app-1 spec: + parentRefs: + - name: my-tls-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: label-tls-app-1 spec: + parentRefs: + - name: my-tls-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 10000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_rules.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_rules.yml new file mode 100644 index 000000000..f6313193c --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_rules.yml @@ -0,0 +1,54 @@ +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway-class + namespace: default +spec: + controllerName: traefik.io/gateway-controller + +--- +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway + namespace: default +spec: + gatewayClassName: my-gateway-class + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS + port: 9000 + tls: + mode: Passthrough + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + +--- +kind: TLSRoute +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: tls-app + namespace: default +spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + rules: + - backendRefs: + - name: whoamitcp + port: 9000 + weight: 1 + kind: Service + group: "" + - backendRefs: + - name: whoamitcp + port: 10000 + weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_all.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_all.yml index 3a93290f4..e9a942afa 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_all.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_all.yml @@ -1,66 +1,71 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 9001 - hostname: foo.example.com tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: All - selector: - matchLabels: - app: tls-app --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-default namespace: default - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - foo.default rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 - matches: - - snis: - - foo.default + kind: Service + group: "" --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-bar namespace: bar - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + namespace: default + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - foo.bar rules: - - forwardTo: - - serviceName: whoamitcp-bar + - backendRefs: + - name: whoamitcp-bar port: 9000 weight: 1 - matches: - - snis: - - foo.bar - + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_same.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_same.yml index 0f7616120..ef81e534c 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_same.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_same.yml @@ -1,65 +1,70 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 9001 - hostname: foo.example.com tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tls-app --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-default namespace: default - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - foo.default rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 - matches: - - snis: - - foo.default + kind: Service + group: "" --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-bar namespace: bar - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - foo.bar rules: - - forwardTo: - - serviceName: whoamitcp-bar + - backendRefs: + - name: whoamitcp-bar port: 9000 weight: 1 - matches: - - snis: - - foo.bar + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_selector.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_selector.yml index cddbf5a2f..c51ed45a2 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_selector.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_selector.yml @@ -8,69 +8,75 @@ metadata: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 9001 - hostname: foo.example.com tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: Selector selector: matchLabels: foo: bar - selector: - matchLabels: - app: tls-app --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-default namespace: default - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - foo.default rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 - matches: - - snis: - - foo.default + kind: Service + group: "" --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-bar namespace: bar - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + namespace: default + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - foo.bar rules: - - forwardTo: - - serviceName: whoamitcp-bar + - backendRefs: + - name: whoamitcp-bar port: 9000 weight: 1 - matches: - - snis: - - foo.bar + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough.yml index 6d34c2abb..2c3369aca 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough.yml @@ -1,44 +1,48 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 9001 hostname: foo.example.com tls: mode: Passthrough - routes: - kind: TLSRoute + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tls-app --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough_tls.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough_tls.yml index 8b718b2c1..da5d22d84 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough_tls.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough_tls.yml @@ -11,50 +11,54 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 9001 hostname: foo.example.com tls: mode: Passthrough # certificateRef is ignored with mode "Passthrough" - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TLSRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: tls-app --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: tls-app spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_http.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_http.yml index 21c9fe572..25411db69 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_http.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_http.yml @@ -1,42 +1,37 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 9001 hostname: foo.example.com - routes: - kind: TLSRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: tls-app --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: tls-app spec: rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_https.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_https.yml index f4ba9656b..782f344aa 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_https.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_https.yml @@ -11,49 +11,43 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTPS + listeners: # Use GatewayClass defaults for listener definition. + - name: https + protocol: HTTPS port: 9001 hostname: foo.example.com tls: mode: Terminate # Default mode - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TLSRoute + certificateRefs: + - kind: Secret + name: supersecret + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: tls-app --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: tls-app spec: rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_tcp.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_tcp.yml index c1f5071dc..b27e1fe7e 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_tcp.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_tcp.yml @@ -1,42 +1,37 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TCP + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp + protocol: TCP port: 9001 hostname: foo.example.com - routes: - kind: TLSRoute + allowedRoutes: namespaces: from: Same - selector: - matchLabels: - app: tls-app --- kind: TLSRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tls-app-1 namespace: default - labels: - app: tls-app spec: rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 9000 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_wrong_service_port.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_wrong_service_port.yml index e6ad0c281..1aafeb234 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_wrong_service_port.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_wrong_service_port.yml @@ -11,47 +11,51 @@ data: --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 8080 tls: - certificateRef: - kind: Secret - name: supersecret - group: core - routes: - kind: TCPRoute + certificateRefs: + - kind: Secret + name: supersecret + group: "" + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp weight: 1 port: 9001 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_gatewayclass.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_gatewayclass.yml index d4944ad90..c053f92e1 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_gatewayclass.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_gatewayclass.yml @@ -1,33 +1,33 @@ --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 8080 - routes: - kind: TCPRoute + allowedRoutes: + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: foo --- kind: TCPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: tcp-app-1 namespace: default - labels: - app: foo spec: rules: - - forwardTo: - - serviceName: whoamitcp + - backendRefs: + - name: whoamitcp port: 8080 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_tlsroute.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_tlsroute.yml index 9a3e281c3..9eb8cc5e0 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_tlsroute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_tlsroute.yml @@ -1,28 +1,28 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: TLS + listeners: # Use GatewayClass defaults for listener definition. + - name: tls + protocol: TLS port: 8080 tls: mode: Passthrough - routes: - kind: TLSRoutes + allowedRoutes: + kinds: + - kind: TLSRoute + group: gateway.networking.k8s.io namespaces: from: Same - selector: - matchLabels: - app: foo diff --git a/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_one_wildcard.yml b/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_one_wildcard.yml index e6718f6f4..5e20fd9bf 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_one_wildcard.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_one_wildcard.yml @@ -1,43 +1,45 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" - "*.bar.com" rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_wildcard.yml b/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_wildcard.yml index d768cf7c2..c368d7fbc 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_wildcard.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_wildcard.yml @@ -1,43 +1,45 @@ --- kind: GatewayClass -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway-class spec: - controller: traefik.io/gateway-controller + controllerName: traefik.io/gateway-controller --- kind: Gateway -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: my-gateway namespace: default spec: gatewayClassName: my-gateway-class - listeners: # Use GatewayClass defaults for listener definition. - - protocol: HTTP + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP port: 80 - routes: - kind: HTTPRoute + allowedRoutes: namespaces: from: Same - selector: - app: foo --- kind: HTTPRoute -apiVersion: networking.x-k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: http-app-1 namespace: default - labels: - app: foo spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io hostnames: - "foo.com" - - "*" + - "*.foo.com" rules: - - forwardTo: - - serviceName: whoami + - backendRefs: + - name: whoami port: 80 weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/kubernetes.go b/pkg/provider/kubernetes/gateway/kubernetes.go index d0be9c5ad..30a0622a0 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes.go +++ b/pkg/provider/kubernetes/gateway/kubernetes.go @@ -20,22 +20,25 @@ import ( "github.com/traefik/traefik/v2/pkg/job" "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/provider" + traefikv1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/tls" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/utils/pointer" - "sigs.k8s.io/gateway-api/apis/v1alpha1" + "k8s.io/utils/strings/slices" + "sigs.k8s.io/gateway-api/apis/v1alpha2" ) const ( - providerName = "kubernetesgateway" - traefikServiceKind = "TraefikService" - traefikServiceGroupName = "traefik.containo.us" - routeHTTPKind = "HTTPRoute" - routeTCPKind = "TCPRoute" - routeTLSKind = "TLSRoute" + providerName = "kubernetesgateway" + + kindGateway = "Gateway" + kindTraefikService = "TraefikService" + kindHTTPRoute = "HTTPRoute" + kindTCPRoute = "TCPRoute" + kindTLSRoute = "TLSRoute" ) // Provider holds configurations of the provider. @@ -99,8 +102,7 @@ func (p *Provider) Init() error { return nil } -// Provide allows the k8s provider to provide configurations to traefik -// using the given configuration channel. +// Provide allows the k8s provider to provide configurations to traefik using the given configuration channel. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { ctxLog := log.With(context.Background(), log.Str(log.ProviderName, providerName)) logger := log.FromContext(ctxLog) @@ -202,18 +204,18 @@ func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Clie } for _, gatewayClass := range gatewayClasses { - if gatewayClass.Spec.Controller == "traefik.io/gateway-controller" { + if gatewayClass.Spec.ControllerName == "traefik.io/gateway-controller" { gatewayClassNames[gatewayClass.Name] = struct{}{} err := client.UpdateGatewayClassStatus(gatewayClass, metav1.Condition{ - Type: string(v1alpha1.GatewayClassConditionStatusAdmitted), + Type: string(v1alpha2.GatewayClassConditionStatusAccepted), Status: metav1.ConditionTrue, Reason: "Handled", Message: "Handled by Traefik controller", LastTransitionTime: metav1.Now(), }) if err != nil { - logger.Errorf("Failed to update %s condition: %v", v1alpha1.GatewayClassConditionStatusAdmitted, err) + logger.Errorf("Failed to update %s condition: %v", v1alpha2.GatewayClassConditionStatusAccepted, err) } } } @@ -225,7 +227,7 @@ func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Clie ctxLog := log.With(ctx, log.Str("gateway", gateway.Name), log.Str("namespace", gateway.Namespace)) logger := log.FromContext(ctxLog) - if _, ok := gatewayClassNames[gateway.Spec.GatewayClassName]; !ok { + if _, ok := gatewayClassNames[string(gateway.Spec.GatewayClassName)]; !ok { continue } @@ -269,7 +271,7 @@ func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Clie return conf } -func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway *v1alpha1.Gateway) (*dynamic.Configuration, error) { +func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway *v1alpha2.Gateway) (*dynamic.Configuration, error) { conf := &dynamic.Configuration{ UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -312,70 +314,39 @@ func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway return conf, nil } -func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *v1alpha1.Gateway, conf *dynamic.Configuration, tlsConfigs map[string]*tls.CertAndStores) []v1alpha1.ListenerStatus { - listenerStatuses := make([]v1alpha1.ListenerStatus, len(gateway.Spec.Listeners)) +func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *v1alpha2.Gateway, conf *dynamic.Configuration, tlsConfigs map[string]*tls.CertAndStores) []v1alpha2.ListenerStatus { logger := log.FromContext(ctx) - allocatedPort := map[v1alpha1.PortNumber]v1alpha1.ProtocolType{} + listenerStatuses := make([]v1alpha2.ListenerStatus, len(gateway.Spec.Listeners)) + allocatedPort := map[v1alpha2.PortNumber]v1alpha2.ProtocolType{} for i, listener := range gateway.Spec.Listeners { - listenerStatuses[i] = v1alpha1.ListenerStatus{ - Port: listener.Port, - Conditions: []metav1.Condition{}, + listenerStatuses[i] = v1alpha2.ListenerStatus{ + Name: listener.Name, + SupportedKinds: []v1alpha2.RouteGroupKind{}, + Conditions: []metav1.Condition{}, } - // Supported Protocol - if listener.Protocol != v1alpha1.HTTPProtocolType && listener.Protocol != v1alpha1.HTTPSProtocolType && - listener.Protocol != v1alpha1.TCPProtocolType && listener.Protocol != v1alpha1.TLSProtocolType { - // update "Detached" status true with "UnsupportedProtocol" reason - listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionDetached), - Status: metav1.ConditionTrue, - LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonUnsupportedProtocol), - Message: fmt.Sprintf("Unsupported listener protocol %q", listener.Protocol), - }) - + supportedKinds, conditions := supportedRouteKinds(listener.Protocol) + if len(conditions) > 0 { + listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, conditions...) continue } - // Supported Route types - if listener.Routes.Kind != routeHTTPKind && listener.Routes.Kind != routeTCPKind && listener.Routes.Kind != routeTLSKind { - // update "ResolvedRefs" status true with "InvalidRoutesRef" reason - listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), - Status: metav1.ConditionFalse, - LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonInvalidRoutesRef), - Message: fmt.Sprintf("Unsupported Route Kind %q", listener.Routes.Kind), - }) - - continue - } - - // Protocol compliant with route type - if listener.Protocol == v1alpha1.HTTPProtocolType && listener.Routes.Kind != routeHTTPKind || - listener.Protocol == v1alpha1.HTTPSProtocolType && listener.Routes.Kind != routeHTTPKind || - listener.Protocol == v1alpha1.TCPProtocolType && listener.Routes.Kind != routeTCPKind || - listener.Protocol == v1alpha1.TLSProtocolType && listener.Routes.Kind != routeTLSKind && listener.Routes.Kind != routeTCPKind { - // update "Detached" status true with "UnsupportedProtocol" reason - listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionDetached), - Status: metav1.ConditionTrue, - LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonUnsupportedProtocol), - Message: fmt.Sprintf("listener protocol %q not supported with route kind %q", listener.Protocol, listener.Routes.Kind), - }) + listenerStatuses[i].SupportedKinds = supportedKinds + routeKinds, conditions := getAllowedRouteKinds(listener, supportedKinds) + if len(conditions) > 0 { + listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, conditions...) continue } if _, ok := allocatedPort[listener.Port]; ok { listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionDetached), + Type: string(v1alpha2.ListenerConditionDetached), Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonPortUnavailable), - Message: fmt.Sprintf("port %d unavailable", listener.Port), + Reason: string(v1alpha2.ListenerReasonPortUnavailable), + Message: fmt.Sprintf("Port %d unavailable", listener.Port), }) continue @@ -386,87 +357,126 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * if err != nil { // update "Detached" status with "PortUnavailable" reason listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionDetached), + Type: string(v1alpha2.ListenerConditionDetached), Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonPortUnavailable), + Reason: string(v1alpha2.ListenerReasonPortUnavailable), Message: fmt.Sprintf("Cannot find entryPoint for Gateway: %v", err), }) continue } + if (listener.Protocol == v1alpha2.HTTPProtocolType || listener.Protocol == v1alpha2.TCPProtocolType) && listener.TLS != nil { + listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ + Type: string(v1alpha2.ListenerConditionDetached), + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Now(), + Reason: "InvalidTLSConfiguration", // TODO check the spec if a proper reason is introduced at some point + Message: "TLS configuration must no be defined when using HTTP or TCP protocol", + }) + + continue + } + // TLS - if listener.Protocol == v1alpha1.HTTPSProtocolType || listener.Protocol == v1alpha1.TLSProtocolType { - if listener.TLS == nil || (listener.TLS.CertificateRef == nil && listener.TLS.Mode != nil && *listener.TLS.Mode != v1alpha1.TLSModePassthrough) { + if listener.Protocol == v1alpha2.HTTPSProtocolType || listener.Protocol == v1alpha2.TLSProtocolType { + if listener.TLS == nil || (len(listener.TLS.CertificateRefs) == 0 && listener.TLS.Mode != nil && *listener.TLS.Mode != v1alpha2.TLSModePassthrough) { // update "Detached" status with "UnsupportedProtocol" reason listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionDetached), + Type: string(v1alpha2.ListenerConditionDetached), Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonUnsupportedProtocol), - Message: fmt.Sprintf("No TLS configuration for Gateway Listener port %d and protocol %q", listener.Port, listener.Protocol), + Reason: "InvalidTLSConfiguration", // TODO check the spec if a proper reason is introduced at some point + Message: fmt.Sprintf("No TLS configuration for Gateway Listener %s:%d and protocol %q", + listener.Name, listener.Port, listener.Protocol), }) continue } - var tlsModeType v1alpha1.TLSModeType + var tlsModeType v1alpha2.TLSModeType if listener.TLS.Mode != nil { tlsModeType = *listener.TLS.Mode } - if tlsModeType == v1alpha1.TLSModePassthrough && listener.TLS.CertificateRef != nil { - // https://gateway-api.sigs.k8s.io/v1alpha1/guides/tls/ + isTLSPassthrough := tlsModeType == v1alpha2.TLSModePassthrough + + if isTLSPassthrough && len(listener.TLS.CertificateRefs) > 0 { + // https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.GatewayTLSConfig logger.Warnf("In case of Passthrough TLS mode, no TLS settings take effect as the TLS session from the client is NOT terminated at the Gateway") } - isTLSPassthrough := tlsModeType == v1alpha1.TLSModePassthrough - // Allowed configurations: - // Protocol TLS -> Passthrough -> TLSRoute - // Protocol TLS -> Terminate -> TCPRoute + // Protocol TLS -> Passthrough -> TLSRoute/TCPRoute + // Protocol TLS -> Terminate -> TLSRoute/TCPRoute // Protocol HTTPS -> Terminate -> HTTPRoute - if !(listener.Protocol == v1alpha1.TLSProtocolType && isTLSPassthrough && listener.Routes.Kind == routeTLSKind || - listener.Protocol == v1alpha1.TLSProtocolType && !isTLSPassthrough && listener.Routes.Kind == routeTCPKind || - listener.Protocol == v1alpha1.HTTPSProtocolType && !isTLSPassthrough && listener.Routes.Kind == routeHTTPKind) { - // update "ConditionDetached" status true with "ReasonUnsupportedProtocol" reason + if listener.Protocol == v1alpha2.HTTPSProtocolType && isTLSPassthrough { listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionDetached), + Type: string(v1alpha2.ListenerConditionDetached), Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonUnsupportedProtocol), - Message: fmt.Sprintf("Unsupported route kind %q with %q", - listener.Routes.Kind, tlsModeType), + Reason: string(v1alpha2.ListenerReasonUnsupportedProtocol), + Message: "HTTPS protocol is not supported with TLS mode Passthrough", }) continue } if !isTLSPassthrough { - if listener.TLS.CertificateRef.Kind != "Secret" || listener.TLS.CertificateRef.Group != "core" { + if len(listener.TLS.CertificateRefs) == 0 { // update "ResolvedRefs" status true with "InvalidCertificateRef" reason listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), + Type: string(v1alpha2.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonInvalidCertificateRef), - Message: fmt.Sprintf("Unsupported TLS CertificateRef group/kind : %v/%v", listener.TLS.CertificateRef.Group, listener.TLS.CertificateRef.Kind), + Reason: string(v1alpha2.ListenerReasonInvalidCertificateRef), + Message: "One TLS CertificateRef is required in Terminate mode", }) continue } - configKey := gateway.Namespace + "/" + listener.TLS.CertificateRef.Name + // TODO Should we support multiple certificates? + certificateRef := listener.TLS.CertificateRefs[0] + + if certificateRef.Kind == nil || *certificateRef.Kind != "Secret" || + certificateRef.Group == nil || (*certificateRef.Group != "" && *certificateRef.Group != "core") { + // update "ResolvedRefs" status true with "InvalidCertificateRef" reason + listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ + Type: string(v1alpha2.ListenerConditionResolvedRefs), + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: string(v1alpha2.ListenerReasonInvalidCertificateRef), + Message: fmt.Sprintf("Unsupported TLS CertificateRef group/kind: %v/%v", certificateRef.Group, certificateRef.Kind), + }) + + continue + } + + // TODO Support ReferencePolicy to support cross namespace references. + if certificateRef.Namespace != nil && string(*certificateRef.Namespace) != gateway.Namespace { + listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ + Type: string(v1alpha2.ListenerConditionResolvedRefs), + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: string(v1alpha2.ListenerReasonInvalidCertificateRef), + Message: "Cross namespace secrets are not supported", + }) + + continue + } + + configKey := gateway.Namespace + "/" + string(certificateRef.Name) if _, tlsExists := tlsConfigs[configKey]; !tlsExists { - tlsConf, err := getTLS(client, listener.TLS.CertificateRef.Name, gateway.Namespace) + tlsConf, err := getTLS(client, certificateRef.Name, gateway.Namespace) if err != nil { // update "ResolvedRefs" status true with "InvalidCertificateRef" reason listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), + Type: string(v1alpha2.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonInvalidCertificateRef), + Reason: string(v1alpha2.ListenerReasonInvalidCertificateRef), Message: fmt.Sprintf("Error while retrieving certificate: %v", err), }) @@ -478,89 +488,238 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * } } - switch listener.Routes.Kind { - case routeHTTPKind: - listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, gatewayHTTPRouteToHTTPConf(ctx, ep, listener, gateway, client, conf)...) - case routeTCPKind: - listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, gatewayTCPRouteToTCPConf(ctx, ep, listener, gateway, client, conf)...) - case routeTLSKind: - listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, gatewayTLSRouteToTCPConf(ctx, ep, listener, gateway, client, conf)...) + for _, routeKind := range routeKinds { + switch routeKind.Kind { + case kindHTTPRoute: + listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, gatewayHTTPRouteToHTTPConf(ctx, ep, listener, gateway, client, conf)...) + case kindTCPRoute: + listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, gatewayTCPRouteToTCPConf(ctx, ep, listener, gateway, client, conf)...) + case kindTLSRoute: + listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, gatewayTLSRouteToTCPConf(ctx, ep, listener, gateway, client, conf)...) + } } } return listenerStatuses } -func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha1.Listener, gateway *v1alpha1.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { - selector := labels.Everything() +func (p *Provider) makeGatewayStatus(listenerStatuses []v1alpha2.ListenerStatus) (v1alpha2.GatewayStatus, error) { + // As Status.Addresses are not implemented yet, we initialize an empty array to follow the API expectations. + gatewayStatus := v1alpha2.GatewayStatus{ + Addresses: []v1alpha2.GatewayAddress{}, + } - if listener.Routes.Selector != nil { - var err error - selector, err = metav1.LabelSelectorAsSelector(listener.Routes.Selector) - if err != nil { - return []metav1.Condition{{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), - Status: metav1.ConditionFalse, + var result error + for i, listener := range listenerStatuses { + if len(listener.Conditions) == 0 { + // GatewayConditionReady "Ready", GatewayConditionReason "ListenerReady" + listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ + Type: string(v1alpha2.ListenerConditionReady), + Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonInvalidRoutesRef), - Message: fmt.Sprintf("Invalid routes selector: %v", err), - }} + Reason: "ListenerReady", + Message: "No error found", + }) + + continue + } + + for _, condition := range listener.Conditions { + result = multierror.Append(result, errors.New(condition.Message)) } } - namespaces, err := getRouteBindingSelectorNamespace(client, gateway.Namespace, listener.Routes.Namespaces) - if err != nil { - // update "ResolvedRefs" status true with "InvalidRoutesRef" reason - return []metav1.Condition{{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), + if result != nil { + // GatewayConditionReady "Ready", GatewayConditionReason "ListenersNotValid" + gatewayStatus.Conditions = append(gatewayStatus.Conditions, metav1.Condition{ + Type: string(v1alpha2.GatewayConditionReady), Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonInvalidRoutesRef), - Message: fmt.Sprintf("Invalid route namespaces selector: %v", err), - }} + Reason: string(v1alpha2.GatewayReasonListenersNotValid), + Message: "All Listeners must be valid", + }) + + return gatewayStatus, result } - httpRoutes, err := client.GetHTTPRoutes(namespaces, selector) - if err != nil { - // update "ResolvedRefs" status true with "InvalidRoutesRef" reason - return []metav1.Condition{{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), - Status: metav1.ConditionFalse, + gatewayStatus.Listeners = listenerStatuses + + gatewayStatus.Conditions = append(gatewayStatus.Conditions, + // update "Scheduled" status with "ResourcesAvailable" reason + metav1.Condition{ + Type: string(v1alpha2.GatewayConditionScheduled), + Status: metav1.ConditionTrue, + Reason: "ResourcesAvailable", + Message: "Resources available", LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonInvalidRoutesRef), - Message: fmt.Sprintf("Cannot fetch %ss: %v", listener.Routes.Kind, err), - }} + }, + // update "Ready" status with "ListenersValid" reason + metav1.Condition{ + Type: string(v1alpha2.GatewayConditionReady), + Status: metav1.ConditionTrue, + Reason: "ListenersValid", + Message: "Listeners valid", + LastTransitionTime: metav1.Now(), + }, + ) + + return gatewayStatus, nil +} + +func (p *Provider) entryPointName(port v1alpha2.PortNumber, protocol v1alpha2.ProtocolType) (string, error) { + portStr := strconv.FormatInt(int64(port), 10) + + for name, entryPoint := range p.EntryPoints { + if strings.HasSuffix(entryPoint.Address, ":"+portStr) { + // If the protocol is HTTP the entryPoint must have no TLS conf + // Not relevant for v1alpha2.TLSProtocolType && v1alpha2.TCPProtocolType + if protocol == v1alpha2.HTTPProtocolType && entryPoint.HasHTTPTLSConf { + continue + } + + return name, nil + } } - if len(httpRoutes) == 0 { - log.FromContext(ctx).Debugf("No HTTPRoutes found for selector %q", selector) - return nil + return "", fmt.Errorf("no matching entryPoint for port %d and protocol %q", port, protocol) +} + +func supportedRouteKinds(protocol v1alpha2.ProtocolType) ([]v1alpha2.RouteGroupKind, []metav1.Condition) { + group := v1alpha2.Group(v1alpha2.GroupName) + + switch protocol { + case v1alpha2.TCPProtocolType: + return []v1alpha2.RouteGroupKind{{Kind: kindTCPRoute, Group: &group}}, nil + + case v1alpha2.HTTPProtocolType, v1alpha2.HTTPSProtocolType: + return []v1alpha2.RouteGroupKind{{Kind: kindHTTPRoute, Group: &group}}, nil + + case v1alpha2.TLSProtocolType: + return []v1alpha2.RouteGroupKind{ + {Kind: kindTCPRoute, Group: &group}, + {Kind: kindTLSRoute, Group: &group}, + }, nil } - var conditions []metav1.Condition - for _, httpRoute := range httpRoutes { - hostRule, err := hostRule(httpRoute.Spec) - if err != nil { + return nil, []metav1.Condition{{ + Type: string(v1alpha2.ListenerConditionDetached), + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Now(), + Reason: string(v1alpha2.ListenerReasonUnsupportedProtocol), + Message: fmt.Sprintf("Unsupported listener protocol %q", protocol), + }} +} + +func getAllowedRouteKinds(listener v1alpha2.Listener, supportedKinds []v1alpha2.RouteGroupKind) ([]v1alpha2.RouteGroupKind, []metav1.Condition) { + if listener.AllowedRoutes == nil || len(listener.AllowedRoutes.Kinds) == 0 { + return supportedKinds, nil + } + + var ( + routeKinds []v1alpha2.RouteGroupKind + conditions []metav1.Condition + ) + + uniqRouteKinds := map[v1alpha2.Kind]struct{}{} + for _, routeKind := range listener.AllowedRoutes.Kinds { + var isSupported bool + for _, kind := range supportedKinds { + if routeKind.Kind == kind.Kind && routeKind.Group != nil && *routeKind.Group == *kind.Group { + isSupported = true + break + } + } + + if !isSupported { conditions = append(conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), - Status: metav1.ConditionFalse, + Type: string(v1alpha2.ListenerConditionDetached), + Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonDegradedRoutes), - Message: fmt.Sprintf("Skipping HTTPRoute %s: invalid hostname: %v", httpRoute.Name, err), + Reason: string(v1alpha2.ListenerReasonInvalidRouteKinds), + Message: fmt.Sprintf("Listener protocol %q does not support RouteGroupKind %v/%s", listener.Protocol, routeKind.Group, routeKind.Kind), }) continue } - for _, routeRule := range httpRoute.Spec.Rules { + if _, exists := uniqRouteKinds[routeKind.Kind]; !exists { + routeKinds = append(routeKinds, routeKind) + uniqRouteKinds[routeKind.Kind] = struct{}{} + } + } + + return routeKinds, conditions +} + +func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha2.Listener, gateway *v1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { + if listener.AllowedRoutes == nil { + // Should not happen due to validation. + return nil + } + + namespaces, err := getRouteBindingSelectorNamespace(client, gateway.Namespace, listener.AllowedRoutes.Namespaces) + if err != nil { + // update "ResolvedRefs" status true with "InvalidRoutesRef" reason + return []metav1.Condition{{ + Type: string(v1alpha2.ListenerConditionResolvedRefs), + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: "InvalidRouteNamespacesSelector", // Should never happen as the selector is validated by kubernetes + Message: fmt.Sprintf("Invalid route namespaces selector: %v", err), + }} + } + + routes, err := client.GetHTTPRoutes(namespaces) + if err != nil { + // update "ResolvedRefs" status true with "InvalidRoutesRef" reason + return []metav1.Condition{{ + Type: string(v1alpha2.ListenerConditionResolvedRefs), + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: string(v1alpha2.ListenerReasonRefNotPermitted), + Message: fmt.Sprintf("Cannot fetch HTTPRoutes: %v", err), + }} + } + + if len(routes) == 0 { + log.FromContext(ctx).Debugf("No HTTPRoutes found") + return nil + } + + var conditions []metav1.Condition + for _, route := range routes { + if !shouldAttach(gateway, listener, route.Namespace, route.Spec.CommonRouteSpec) { + continue + } + + hostnames := matchingHostnames(listener, route.Spec.Hostnames) + if len(hostnames) == 0 && listener.Hostname != nil && *listener.Hostname != "" && len(route.Spec.Hostnames) > 0 { + // TODO update the corresponding route parent status + // https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.TLSRoute + continue + } + + hostRule, err := hostRule(hostnames) + if err != nil { + conditions = append(conditions, metav1.Condition{ + Type: string(v1alpha2.ListenerConditionResolvedRefs), + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: "InvalidRouteHostname", // TODO check the spec if a proper reason is introduced at some point + Message: fmt.Sprintf("Skipping HTTPRoute %s: invalid hostname: %v", route.Name, err), + }) + continue + } + + for _, routeRule := range route.Spec.Rules { rule, err := extractRule(routeRule, hostRule) if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), + Type: string(v1alpha2.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonDegradedRoutes), - Message: fmt.Sprintf("Skipping %s %s: cannot generate rule: %v", listener.Routes.Kind, httpRoute.Name, err), + Reason: "UnsupportedPathOrHeaderType", // TODO check the spec if a proper reason is introduced at some point + Message: fmt.Sprintf("Skipping HTTPRoute %s: cannot generate rule: %v", route.Name, err), }) } @@ -569,45 +728,45 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha EntryPoints: []string{ep}, } - if listener.TLS != nil { + if listener.Protocol == v1alpha2.HTTPSProtocolType && listener.TLS != nil { // TODO support let's encrypt router.TLS = &dynamic.RouterTLSConfig{} } - // Adding the gateway name and the entryPoint name prevents overlapping of routers build from the same routes. - routerName := httpRoute.Name + "-" + gateway.Name + "-" + ep - routerKey, err := makeRouterKey(router.Rule, makeID(httpRoute.Namespace, routerName)) + // Adding the gateway desc and the entryPoint desc prevents overlapping of routers build from the same routes. + routerName := route.Name + "-" + gateway.Name + "-" + ep + routerKey, err := makeRouterKey(router.Rule, makeID(route.Namespace, routerName)) if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), + Type: string(v1alpha2.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonDegradedRoutes), - Message: fmt.Sprintf("Skipping %s %s: cannot make router's key with rule %s: %v", listener.Routes.Kind, httpRoute.Name, router.Rule, err), + Reason: "InvalidRouterKey", // Should never happen + Message: fmt.Sprintf("Skipping HTTPRoute %s: cannot make router's key with rule %s: %v", route.Name, router.Rule, err), }) // TODO update the RouteStatus condition / deduplicate conditions on listener continue } - if routeRule.ForwardTo == nil { + if len(routeRule.BackendRefs) == 0 { continue } - // Traefik internal service can be used only if there is only one ForwardTo service reference. - if len(routeRule.ForwardTo) == 1 && isInternalService(routeRule.ForwardTo[0]) { - router.Service = routeRule.ForwardTo[0].BackendRef.Name + // Traefik internal service can be used only if there is only one BackendRef service reference. + if len(routeRule.BackendRefs) == 1 && isInternalService(routeRule.BackendRefs[0].BackendRef) { + router.Service = string(routeRule.BackendRefs[0].Name) } else { - wrrService, subServices, err := loadServices(client, httpRoute.Namespace, routeRule.ForwardTo) + wrrService, subServices, err := loadServices(client, route.Namespace, routeRule.BackendRefs) if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), + Type: string(v1alpha2.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonDegradedRoutes), - Message: fmt.Sprintf("Cannot load service from %s %s/%s: %v", listener.Routes.Kind, httpRoute.Namespace, httpRoute.Name, err), + Reason: "InvalidBackendRefs", // TODO check the spec if a proper reason is introduced at some point + Message: fmt.Sprintf("Cannot load HTTPRoute service %s/%s: %v", route.Namespace, route.Name, err), }) // TODO update the RouteStatus condition / deduplicate conditions on listener @@ -632,108 +791,95 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha return conditions } -func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha1.Listener, gateway *v1alpha1.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { - selector := labels.Everything() - - if listener.Routes.Selector != nil { - var err error - selector, err = metav1.LabelSelectorAsSelector(listener.Routes.Selector) - if err != nil { - return []metav1.Condition{{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), - Status: metav1.ConditionFalse, - LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonInvalidRoutesRef), - Message: fmt.Sprintf("Invalid routes selector: %v", err), - }} - } +func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.Listener, gateway *v1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { + if listener.AllowedRoutes == nil { + // Should not happen due to validation. + return nil } - namespaces, err := getRouteBindingSelectorNamespace(client, gateway.Namespace, listener.Routes.Namespaces) + namespaces, err := getRouteBindingSelectorNamespace(client, gateway.Namespace, listener.AllowedRoutes.Namespaces) if err != nil { // update "ResolvedRefs" status true with "InvalidRoutesRef" reason return []metav1.Condition{{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), + Type: string(v1alpha2.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonInvalidRoutesRef), + Reason: "InvalidRouteNamespacesSelector", // TODO should never happen as the selector is validated by Kubernetes Message: fmt.Sprintf("Invalid route namespaces selector: %v", err), }} } - tcpRoutes, err := client.GetTCPRoutes(namespaces, selector) + routes, err := client.GetTCPRoutes(namespaces) if err != nil { // update "ResolvedRefs" status true with "InvalidRoutesRef" reason return []metav1.Condition{{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), + Type: string(v1alpha2.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonInvalidRoutesRef), - Message: fmt.Sprintf("Cannot fetch %ss: %v", listener.Routes.Kind, err), + Reason: string(v1alpha2.ListenerReasonRefNotPermitted), + Message: fmt.Sprintf("Cannot fetch TCPRoutes: %v", err), }} } - if len(tcpRoutes) == 0 { - log.FromContext(ctx).Debugf("No TCPRoutes found for selector %q", selector) + if len(routes) == 0 { + log.FromContext(ctx).Debugf("No TCPRoutes found") return nil } var conditions []metav1.Condition - for _, tcpRoute := range tcpRoutes { - if len(tcpRoute.Spec.Rules) > 1 { - conditions = append(conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), - Status: metav1.ConditionFalse, - LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonDegradedRoutes), - Message: fmt.Sprintf("Skipping %s %s: multiple rules are not supported", listener.Routes.Kind, tcpRoute.Name), - }) + for _, route := range routes { + if !shouldAttach(gateway, listener, route.Namespace, route.Spec.CommonRouteSpec) { continue } - for _, routeRule := range tcpRoute.Spec.Rules { - router := dynamic.TCPRouter{ - Rule: "HostSNI(`*`)", // Gateway listener hostname not available in TCP - EntryPoints: []string{ep}, + router := dynamic.TCPRouter{ + Rule: "HostSNI(`*`)", // Gateway listener hostname not available in TCP + EntryPoints: []string{ep}, + } + + if listener.Protocol == v1alpha2.TLSProtocolType && listener.TLS != nil { + // TODO support let's encrypt + router.TLS = &dynamic.RouterTCPTLSConfig{ + Passthrough: listener.TLS.Mode != nil && *listener.TLS.Mode == v1alpha2.TLSModePassthrough, } + } - if listener.TLS != nil { - // TODO support let's encrypt - router.TLS = &dynamic.RouterTCPTLSConfig{} - } + // Adding the gateway desc and the entryPoint desc prevents overlapping of routers build from the same routes. + routerName := route.Name + "-" + gateway.Name + "-" + ep + routerKey, err := makeRouterKey("", makeID(route.Namespace, routerName)) + if err != nil { + // update "ResolvedRefs" status true with "DroppedRoutes" reason + conditions = append(conditions, metav1.Condition{ + Type: string(v1alpha2.ListenerConditionResolvedRefs), + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: "InvalidRouterKey", // Should never happen + Message: fmt.Sprintf("Skipping TCPRoute %s: cannot make router's key with rule %s: %v", route.Name, router.Rule, err), + }) - // Adding the gateway name and the entryPoint name prevents overlapping of routers build from the same routes. - routerName := tcpRoute.Name + "-" + gateway.Name + "-" + ep - routerKey, err := makeRouterKey("", makeID(tcpRoute.Namespace, routerName)) - if err != nil { - // update "ResolvedRefs" status true with "DroppedRoutes" reason - conditions = append(conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), - Status: metav1.ConditionFalse, - LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonDegradedRoutes), - Message: fmt.Sprintf("Skipping %s %s: cannot make router's key with rule %s: %v", listener.Routes.Kind, tcpRoute.Name, router.Rule, err), - }) + // TODO update the RouteStatus condition / deduplicate conditions on listener + continue + } - // TODO update the RouteStatus condition / deduplicate conditions on listener + routerKey = provider.Normalize(routerKey) + + var ruleServiceNames []string + for i, rule := range route.Spec.Rules { + if rule.BackendRefs == nil { + // Should not happen due to validation. + // https://github.com/kubernetes-sigs/gateway-api/blob/v0.4.0/apis/v1alpha2/tcproute_types.go#L76 continue } - // Should not happen due to validation - // https://github.com/kubernetes-sigs/gateway-api/blob/af68a622f072811767d246ef5897135d93af0704/apis/v1alpha1/tcproute_types.go#L76 - if routeRule.ForwardTo == nil { - continue - } - - wrrService, subServices, err := loadTCPServices(client, tcpRoute.Namespace, routeRule.ForwardTo) + wrrService, subServices, err := loadTCPServices(client, route.Namespace, rule.BackendRefs) if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), + Type: string(v1alpha2.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonDegradedRoutes), - Message: fmt.Sprintf("Cannot load service from %s %s/%s: %v", listener.Routes.Kind, tcpRoute.Namespace, tcpRoute.Name, err), + Reason: "InvalidBackendRefs", // TODO check the spec if a proper reason is introduced at some point + Message: fmt.Sprintf("Cannot load TCPRoute service %s/%s: %v", route.Namespace, route.Name, err), }) // TODO update the RouteStatus condition / deduplicate conditions on listener @@ -744,123 +890,143 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha1. conf.TCP.Services[svcName] = svc } - serviceName := provider.Normalize(routerKey + "-wrr") + serviceName := fmt.Sprintf("%s-wrr-%d", routerKey, i) conf.TCP.Services[serviceName] = wrrService - router.Service = serviceName - - routerKey = provider.Normalize(routerKey) - conf.TCP.Routers[routerKey] = &router + ruleServiceNames = append(ruleServiceNames, serviceName) } + + if len(ruleServiceNames) == 1 { + router.Service = ruleServiceNames[0] + conf.TCP.Routers[routerKey] = &router + continue + } + + routeServiceKey := routerKey + "-wrr" + routeService := &dynamic.TCPService{Weighted: &dynamic.TCPWeightedRoundRobin{}} + + for _, name := range ruleServiceNames { + service := dynamic.TCPWRRService{Name: name} + service.SetDefaults() + + routeService.Weighted.Services = append(routeService.Weighted.Services, service) + } + + conf.TCP.Services[routeServiceKey] = routeService + + router.Service = routeServiceKey + conf.TCP.Routers[routerKey] = &router } return conditions } -func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha1.Listener, gateway *v1alpha1.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { - selector := labels.Everything() - - if listener.Routes.Selector != nil { - var err error - selector, err = metav1.LabelSelectorAsSelector(listener.Routes.Selector) - if err != nil { - return []metav1.Condition{{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), - Status: metav1.ConditionFalse, - LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonInvalidRoutesRef), - Message: fmt.Sprintf("Invalid routes selector: %v", err), - }} - } +func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.Listener, gateway *v1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { + if listener.AllowedRoutes == nil { + // Should not happen due to validation. + return nil } - namespaces, err := getRouteBindingSelectorNamespace(client, gateway.Namespace, listener.Routes.Namespaces) + namespaces, err := getRouteBindingSelectorNamespace(client, gateway.Namespace, listener.AllowedRoutes.Namespaces) if err != nil { // update "ResolvedRefs" status true with "InvalidRoutesRef" reason return []metav1.Condition{{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), + Type: string(v1alpha2.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonInvalidRoutesRef), + Reason: "InvalidRouteNamespacesSelector", // TODO should never happen as the selector is validated by Kubernetes Message: fmt.Sprintf("Invalid route namespaces selector: %v", err), }} } - tlsRoutes, err := client.GetTLSRoutes(namespaces, selector) + routes, err := client.GetTLSRoutes(namespaces) if err != nil { // update "ResolvedRefs" status true with "InvalidRoutesRef" reason return []metav1.Condition{{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), + Type: string(v1alpha2.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonInvalidRoutesRef), - Message: fmt.Sprintf("Cannot fetch %ss: %v", listener.Routes.Kind, err), + Reason: string(v1alpha2.ListenerReasonRefNotPermitted), + Message: fmt.Sprintf("Cannot fetch TLSRoutes: %v", err), }} } - if len(tlsRoutes) == 0 { - log.FromContext(ctx).Debugf("No TLSRoutes found for selector %q", selector) + if len(routes) == 0 { + log.FromContext(ctx).Debugf("No TLSRoutes found") return nil } var conditions []metav1.Condition - for _, tlsRoute := range tlsRoutes { - for _, routeRule := range tlsRoute.Spec.Rules { - rule, err := hostSNIRule(routeRule) - if err != nil { - // update "ResolvedRefs" status true with "DroppedRoutes" reason - conditions = append(conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), - Status: metav1.ConditionFalse, - LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonDegradedRoutes), - Message: fmt.Sprintf("Skipping %s %s: cannot make route's SNI match: %v", listener.Routes.Kind, tlsRoute.Name, err), - }) - // TODO update the RouteStatus condition / deduplicate conditions on listener + for _, route := range routes { + if !shouldAttach(gateway, listener, route.Namespace, route.Spec.CommonRouteSpec) { + continue + } + + hostnames := matchingHostnames(listener, route.Spec.Hostnames) + if len(hostnames) == 0 && listener.Hostname != nil && *listener.Hostname != "" && len(route.Spec.Hostnames) > 0 { + // TODO update the corresponding route parent status + // https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.TLSRoute + continue + } + + rule, err := hostSNIRule(hostnames) + if err != nil { + // update "ResolvedRefs" status true with "DroppedRoutes" reason + conditions = append(conditions, metav1.Condition{ + Type: string(v1alpha2.ListenerConditionResolvedRefs), + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: "InvalidHostnames", // TODO check the spec if a proper reason is introduced at some point + Message: fmt.Sprintf("Skipping TLSRoute %s: cannot make route's SNI match: %v", route.Name, err), + }) + // TODO update the RouteStatus condition / deduplicate conditions on listener + continue + } + + router := dynamic.TCPRouter{ + Rule: rule, + EntryPoints: []string{ep}, + TLS: &dynamic.RouterTCPTLSConfig{ + Passthrough: listener.TLS.Mode != nil && *listener.TLS.Mode == v1alpha2.TLSModePassthrough, + }, + } + + // Adding the gateway desc and the entryPoint desc prevents overlapping of routers build from the same routes. + routerName := route.Name + "-" + gateway.Name + "-" + ep + routerKey, err := makeRouterKey(rule, makeID(route.Namespace, routerName)) + if err != nil { + // update "ResolvedRefs" status true with "DroppedRoutes" reason + conditions = append(conditions, metav1.Condition{ + Type: string(v1alpha2.ListenerConditionResolvedRefs), + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: "InvalidRouterKey", // Should never happen + Message: fmt.Sprintf("Skipping TLSRoute %s: cannot make router's key with rule %s: %v", route.Name, router.Rule, err), + }) + + // TODO update the RouteStatus condition / deduplicate conditions on listener + continue + } + + routerKey = provider.Normalize(routerKey) + + var ruleServiceNames []string + for i, routeRule := range route.Spec.Rules { + if len(routeRule.BackendRefs) == 0 { + // Should not happen due to validation. + // https://github.com/kubernetes-sigs/gateway-api/blob/v0.4.0/apis/v1alpha2/tlsroute_types.go#L120 continue } - router := dynamic.TCPRouter{ - Rule: rule, - EntryPoints: []string{ep}, - // The TLS Passthrough is the only TLS mode supported by a Gateway TLSRoute. - TLS: &dynamic.RouterTCPTLSConfig{ - Passthrough: true, - }, - } - - // Adding the gateway name and the entryPoint name prevents overlapping of routers build from the same routes. - routerName := tlsRoute.Name + "-" + gateway.Name + "-" + ep - routerKey, err := makeRouterKey(rule, makeID(tlsRoute.Namespace, routerName)) + wrrService, subServices, err := loadTCPServices(client, route.Namespace, routeRule.BackendRefs) if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), + Type: string(v1alpha2.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonDegradedRoutes), - Message: fmt.Sprintf("Skipping %s %s: cannot make router's key with rule %s: %v", listener.Routes.Kind, tlsRoute.Name, router.Rule, err), - }) - - // TODO update the RouteStatus condition / deduplicate conditions on listener - continue - } - - // Should not happen due to validation - // https://github.com/kubernetes-sigs/gateway-api/blob/af68a622f072811767d246ef5897135d93af0704/apis/v1alpha1/tlsroute_types.go#L79 - if routeRule.ForwardTo == nil { - continue - } - - wrrService, subServices, err := loadTCPServices(client, tlsRoute.Namespace, routeRule.ForwardTo) - if err != nil { - // update "ResolvedRefs" status true with "DroppedRoutes" reason - conditions = append(conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionResolvedRefs), - Status: metav1.ConditionFalse, - LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.ListenerReasonDegradedRoutes), - Message: fmt.Sprintf("Cannot load service from %s %s/%s: %v", listener.Routes.Kind, tlsRoute.Namespace, tlsRoute.Name, err), + Reason: "InvalidBackendRefs", // TODO check the spec if a proper reason is introduced at some point + Message: fmt.Sprintf("Cannot load TLSRoute service %s/%s: %v", route.Namespace, route.Name, err), }) // TODO update the RouteStatus condition / deduplicate conditions on listener @@ -871,32 +1037,121 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha1. conf.TCP.Services[svcName] = svc } - serviceName := provider.Normalize(routerKey + "-wrr") + serviceName := fmt.Sprintf("%s-wrr-%d", routerKey, i) conf.TCP.Services[serviceName] = wrrService - router.Service = serviceName - - routerKey = provider.Normalize(routerKey) - conf.TCP.Routers[routerKey] = &router + ruleServiceNames = append(ruleServiceNames, serviceName) } + + if len(ruleServiceNames) == 1 { + router.Service = ruleServiceNames[0] + conf.TCP.Routers[routerKey] = &router + continue + } + + routeServiceKey := routerKey + "-wrr" + routeService := &dynamic.TCPService{Weighted: &dynamic.TCPWeightedRoundRobin{}} + + for _, name := range ruleServiceNames { + service := dynamic.TCPWRRService{Name: name} + service.SetDefaults() + + routeService.Weighted.Services = append(routeService.Weighted.Services, service) + } + + conf.TCP.Services[routeServiceKey] = routeService + + router.Service = routeServiceKey + conf.TCP.Routers[routerKey] = &router } return conditions } -func getRouteBindingSelectorNamespace(client Client, gatewayNamespace string, routeNamespaces *v1alpha1.RouteNamespaces) ([]string, error) { +// Because of Kubernetes validation we admit that the given Hostnames are valid. +// https://github.com/kubernetes-sigs/gateway-api/blob/ff9883da4cad8554cd300394f725ab3a27502785/apis/v1alpha2/shared_types.go#L252 +func matchingHostnames(listener v1alpha2.Listener, hostnames []v1alpha2.Hostname) []v1alpha2.Hostname { + if listener.Hostname == nil || *listener.Hostname == "" { + return hostnames + } + + if len(hostnames) == 0 { + return []v1alpha2.Hostname{*listener.Hostname} + } + + listenerLabels := strings.Split(string(*listener.Hostname), ".") + + var matches []v1alpha2.Hostname + + for _, hostname := range hostnames { + if hostname == *listener.Hostname { + matches = append(matches, hostname) + continue + } + + hostnameLabels := strings.Split(string(hostname), ".") + if len(listenerLabels) != len(hostnameLabels) { + continue + } + + if !slices.Equal(listenerLabels[1:], hostnameLabels[1:]) { + continue + } + + if listenerLabels[0] == "*" { + matches = append(matches, hostname) + continue + } + + if hostnameLabels[0] == "*" { + matches = append(matches, *listener.Hostname) + continue + } + } + + return matches +} + +func shouldAttach(gateway *v1alpha2.Gateway, listener v1alpha2.Listener, routeNamespace string, routeSpec v1alpha2.CommonRouteSpec) bool { + for _, parentRef := range routeSpec.ParentRefs { + if parentRef.Group == nil || *parentRef.Group != v1alpha2.GroupName { + continue + } + + if parentRef.Kind == nil || *parentRef.Kind != kindGateway { + continue + } + + if parentRef.SectionName != nil && *parentRef.SectionName != listener.Name { + continue + } + + namespace := routeNamespace + if parentRef.Namespace != nil { + namespace = string(*parentRef.Namespace) + } + + if namespace == gateway.Namespace && string(parentRef.Name) == gateway.Name { + return true + } + } + + return false +} + +func getRouteBindingSelectorNamespace(client Client, gatewayNamespace string, routeNamespaces *v1alpha2.RouteNamespaces) ([]string, error) { if routeNamespaces == nil || routeNamespaces.From == nil { return []string{gatewayNamespace}, nil } switch *routeNamespaces.From { - case v1alpha1.RouteSelectAll: + case v1alpha2.NamespacesFromAll: return []string{metav1.NamespaceAll}, nil - case v1alpha1.RouteSelectSame: + case v1alpha2.NamespacesFromSame: return []string{gatewayNamespace}, nil - case v1alpha1.RouteSelectSelector: + case v1alpha2.NamespacesFromSelector: selector, err := metav1.LabelSelectorAsSelector(routeNamespaces.Selector) if err != nil { return nil, fmt.Errorf("malformed selector: %w", err) @@ -908,74 +1163,11 @@ func getRouteBindingSelectorNamespace(client Client, gatewayNamespace string, ro return nil, fmt.Errorf("unsupported RouteSelectType: %q", *routeNamespaces.From) } -func (p *Provider) makeGatewayStatus(listenerStatuses []v1alpha1.ListenerStatus) (v1alpha1.GatewayStatus, error) { - // As Status.Addresses are not implemented yet, we initialize an empty array to follow the API expectations. - gatewayStatus := v1alpha1.GatewayStatus{ - Addresses: []v1alpha1.GatewayAddress{}, - } - - var result error - for i, listener := range listenerStatuses { - if len(listener.Conditions) == 0 { - // GatewayConditionReady "Ready", GatewayConditionReason "ListenerReady" - listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(v1alpha1.ListenerConditionReady), - Status: metav1.ConditionTrue, - LastTransitionTime: metav1.Now(), - Reason: "ListenerReady", - Message: "No error found", - }) - - continue - } - - for _, condition := range listener.Conditions { - result = multierror.Append(result, errors.New(condition.Message)) - } - } - - if result != nil { - // GatewayConditionReady "Ready", GatewayConditionReason "ListenersNotValid" - gatewayStatus.Conditions = append(gatewayStatus.Conditions, metav1.Condition{ - Type: string(v1alpha1.GatewayConditionReady), - Status: metav1.ConditionFalse, - LastTransitionTime: metav1.Now(), - Reason: string(v1alpha1.GatewayReasonListenersNotValid), - Message: "All Listeners must be valid", - }) - - return gatewayStatus, result - } - - gatewayStatus.Listeners = listenerStatuses - - gatewayStatus.Conditions = append(gatewayStatus.Conditions, - // update "Scheduled" status with "ResourcesAvailable" reason - metav1.Condition{ - Type: string(v1alpha1.GatewayConditionScheduled), - Status: metav1.ConditionTrue, - Reason: "ResourcesAvailable", - Message: "Resources available", - LastTransitionTime: metav1.Now(), - }, - // update "Ready" status with "ListenersValid" reason - metav1.Condition{ - Type: string(v1alpha1.GatewayConditionReady), - Status: metav1.ConditionTrue, - Reason: "ListenersValid", - Message: "Listeners valid", - LastTransitionTime: metav1.Now(), - }, - ) - - return gatewayStatus, nil -} - -func hostRule(httpRouteSpec v1alpha1.HTTPRouteSpec) (string, error) { +func hostRule(hostnames []v1alpha2.Hostname) (string, error) { var hostNames []string var hostRegexNames []string - for _, hostname := range httpRouteSpec.Hostnames { + for _, hostname := range hostnames { host := string(hostname) // When unspecified, "", or *, all hostnames are matched. // This field can be omitted for protocols that don't require hostname based matching. @@ -990,7 +1182,7 @@ func hostRule(httpRouteSpec v1alpha1.HTTPRouteSpec) (string, error) { continue } - // https://gateway-api.sigs.k8s.io/v1alpha1/references/spec/#networking.x-k8s.io/v1alpha1.Hostname + // https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.Hostname if !strings.HasPrefix(host, "*.") || wildcard > 1 { return "", fmt.Errorf("invalid rule: %q", host) } @@ -1016,39 +1208,38 @@ func hostRule(httpRouteSpec v1alpha1.HTTPRouteSpec) (string, error) { return hostRegexp, nil } -func hostSNIRule(rule v1alpha1.TLSRouteRule) (string, error) { - uniqHostnames := map[string]struct{}{} - var hostnames []string - for _, match := range rule.Matches { - for _, hostname := range match.SNIs { - if len(hostname) == 0 { - continue - } +func hostSNIRule(hostnames []v1alpha2.Hostname) (string, error) { + var matchers []string + uniqHostnames := map[v1alpha2.Hostname]struct{}{} - h := string(hostname) - - // first naive validation, should be improved - wildcardNb := strings.Count(h, "*") - if wildcardNb != 0 && !strings.HasPrefix(h, "*.") || wildcardNb > 1 { - return "", fmt.Errorf("invalid hostname: %q", h) - } - - hostname := "`" + h + "`" - if _, ok := uniqHostnames[hostname]; !ok { - hostnames = append(hostnames, hostname) - uniqHostnames[hostname] = struct{}{} - } + for _, hostname := range hostnames { + if len(hostname) == 0 { + continue } + + if _, exists := uniqHostnames[hostname]; exists { + continue + } + + h := string(hostname) + + // TODO support wildcard hostnames with an HostSNI regexp matcher + if strings.Contains(h, "*") { + return "", fmt.Errorf("wildcard hostname is not supported: %q", h) + } + + matchers = append(matchers, "`"+h+"`") + uniqHostnames[hostname] = struct{}{} } - if len(hostnames) == 0 { + if len(matchers) == 0 { return "HostSNI(`*`)", nil } - return "HostSNI(" + strings.Join(hostnames, ",") + ")", nil + return "HostSNI(" + strings.Join(matchers, ",") + ")", nil } -func extractRule(routeRule v1alpha1.HTTPRouteRule, hostRule string) (string, error) { +func extractRule(routeRule v1alpha2.HTTPRouteRule, hostRule string) (string, error) { var rule string var matchesRules []string @@ -1058,37 +1249,25 @@ func extractRule(routeRule v1alpha1.HTTPRouteRule, hostRule string) (string, err } var matchRules []string - // TODO handle other path types - if match.Path != nil && match.Path.Type != nil && match.Path.Value != nil { - val := pointer.StringDeref(match.Path.Value, "") + if match.Path != nil && match.Path.Type != nil && match.Path.Value != nil { + // TODO handle other path types switch *match.Path.Type { - case v1alpha1.PathMatchExact: - matchRules = append(matchRules, fmt.Sprintf("Path(`%s`)", val)) - case v1alpha1.PathMatchPrefix: - matchRules = append(matchRules, fmt.Sprintf("PathPrefix(`%s`)", val)) + case v1alpha2.PathMatchExact: + matchRules = append(matchRules, fmt.Sprintf("Path(`%s`)", *match.Path.Value)) + case v1alpha2.PathMatchPathPrefix: + matchRules = append(matchRules, fmt.Sprintf("PathPrefix(`%s`)", *match.Path.Value)) default: return "", fmt.Errorf("unsupported path match %s", *match.Path.Type) } } - // TODO handle other headers types - if match.Headers != nil && match.Headers.Type != nil { - switch *match.Headers.Type { - case v1alpha1.HeaderMatchExact: - var headerRules []string - - for headerName, headerValue := range match.Headers.Values { - headerRules = append(headerRules, fmt.Sprintf("Headers(`%s`,`%s`)", headerName, headerValue)) - } - // to have a consistent order - sort.Strings(headerRules) - matchRules = append(matchRules, headerRules...) - default: - return "", fmt.Errorf("unsupported header match type %s", *match.Headers.Type) - } + headerRules, err := extractHeaderRules(match.Headers) + if err != nil { + return "", err } + matchRules = append(matchRules, headerRules...) matchesRules = append(matchesRules, strings.Join(matchRules, " && ")) } @@ -1117,22 +1296,25 @@ func extractRule(routeRule v1alpha1.HTTPRouteRule, hostRule string) (string, err return rule + "(" + strings.Join(matchesRules, " || ") + ")", nil } -func (p *Provider) entryPointName(port v1alpha1.PortNumber, protocol v1alpha1.ProtocolType) (string, error) { - portStr := strconv.FormatInt(int64(port), 10) +func extractHeaderRules(headers []v1alpha2.HTTPHeaderMatch) ([]string, error) { + var headerRules []string - for name, entryPoint := range p.EntryPoints { - if strings.HasSuffix(entryPoint.Address, ":"+portStr) { - // if the protocol is HTTP the entryPoint must have no TLS conf - // Not relevant for v1alpha1.TLSProtocolType && v1alpha1.TCPProtocolType - if protocol == v1alpha1.HTTPProtocolType && entryPoint.HasHTTPTLSConf { - continue - } + // TODO handle other headers types + for _, header := range headers { + if header.Type == nil { + // Should never happen due to kubernetes validation. + continue + } - return name, nil + switch *header.Type { + case v1alpha2.HeaderMatchExact: + headerRules = append(headerRules, fmt.Sprintf("Headers(`%s`,`%s`)", header.Name, header.Value)) + default: + return nil, fmt.Errorf("unsupported header match type %s", *header.Type) } } - return "", fmt.Errorf("no matching entryPoint for port %d and protocol %q", port, protocol) + return headerRules, nil } func makeRouterKey(rule, name string) (string, error) { @@ -1154,8 +1336,8 @@ func makeID(namespace, name string) string { return namespace + "-" + name } -func getTLS(k8sClient Client, secretName, namespace string) (*tls.CertAndStores, error) { - secret, exists, err := k8sClient.GetSecret(namespace, secretName) +func getTLS(k8sClient Client, secretName v1alpha2.ObjectName, namespace string) (*tls.CertAndStores, error) { + secret, exists, err := k8sClient.GetSecret(namespace, string(secretName)) if err != nil { return nil, fmt.Errorf("failed to fetch secret %s/%s: %w", namespace, secretName, err) } @@ -1163,7 +1345,7 @@ func getTLS(k8sClient Client, secretName, namespace string) (*tls.CertAndStores, return nil, fmt.Errorf("secret %s/%s does not exist", namespace, secretName) } - cert, key, err := getCertificateBlocks(secret, namespace, secretName) + cert, key, err := getCertificateBlocks(secret, namespace, string(secretName)) if err != nil { return nil, err } @@ -1228,7 +1410,7 @@ func getCertificateBlocks(secret *corev1.Secret, namespace, secretName string) ( } // loadServices is generating a WRR service, even when there is only one target. -func loadServices(client Client, namespace string, targets []v1alpha1.HTTPRouteForwardTo) (*dynamic.Service, map[string]*dynamic.Service, error) { +func loadServices(client Client, namespace string, backendRefs []v1alpha2.HTTPBackendRef) (*dynamic.Service, map[string]*dynamic.Service, error) { services := map[string]*dynamic.Service{} wrrSvc := &dynamic.Service{ @@ -1237,33 +1419,35 @@ func loadServices(client Client, namespace string, targets []v1alpha1.HTTPRouteF }, } - for _, forwardTo := range targets { - weight := int(pointer.Int32Deref(forwardTo.Weight, 1)) - - if forwardTo.ServiceName == nil && forwardTo.BackendRef != nil { - if !(forwardTo.BackendRef.Group == traefikServiceGroupName && forwardTo.BackendRef.Kind == traefikServiceKind) { - continue - } - - if strings.HasSuffix(forwardTo.BackendRef.Name, "@internal") { - return nil, nil, fmt.Errorf("traefik internal service %s is not allowed in a WRR loadbalancer", forwardTo.BackendRef.Name) - } - - wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.WRRService{Name: forwardTo.BackendRef.Name, Weight: &weight}) + for _, backendRef := range backendRefs { + if backendRef.Group == nil || backendRef.Kind == nil { + // Should not happen as this is validated by kubernetes continue } - if forwardTo.ServiceName == nil { + if isInternalService(backendRef.BackendRef) { + return nil, nil, fmt.Errorf("traefik internal service %s is not allowed in a WRR loadbalancer", backendRef.BackendRef.Name) + } + + weight := int(pointer.Int32Deref(backendRef.Weight, 1)) + + if *backendRef.Group == traefikv1alpha1.GroupName && *backendRef.Kind == kindTraefikService { + wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.WRRService{Name: string(backendRef.Name), Weight: &weight}) continue } + if *backendRef.Group != "" && *backendRef.Group != "core" && *backendRef.Kind != "Service" { + return nil, nil, fmt.Errorf("unsupported HTTPBackendRef %s/%s/%s", *backendRef.Group, *backendRef.Kind, backendRef.Name) + } + svc := dynamic.Service{ LoadBalancer: &dynamic.ServersLoadBalancer{ PassHostHeader: pointer.Bool(true), }, } - service, exists, err := client.GetService(namespace, *forwardTo.ServiceName) + // TODO support cross namespace through ReferencePolicy + service, exists, err := client.GetService(namespace, string(backendRef.Name)) if err != nil { return nil, nil, err } @@ -1272,7 +1456,7 @@ func loadServices(client Client, namespace string, targets []v1alpha1.HTTPRouteF return nil, nil, errors.New("service not found") } - if len(service.Spec.Ports) > 1 && forwardTo.Port == nil { + if len(service.Spec.Ports) > 1 && backendRef.Port == nil { // If the port is unspecified and the backend is a Service // object consisting of multiple port definitions, the route // must be dropped from the Gateway. The controller should @@ -1280,7 +1464,7 @@ func loadServices(client Client, namespace string, targets []v1alpha1.HTTPRouteF // "DroppedRoutes" reason. The gateway status for this route // should be updated with a condition that describes the error // more specifically. - log.WithoutContext().Errorf("A multiple ports Kubernetes Service cannot be used if unspecified forwardTo.Port") + log.WithoutContext().Errorf("A multiple ports Kubernetes Service cannot be used if unspecified backendRef.Port") continue } @@ -1288,7 +1472,7 @@ func loadServices(client Client, namespace string, targets []v1alpha1.HTTPRouteF var match bool for _, p := range service.Spec.Ports { - if forwardTo.Port == nil || p.Port == int32(*forwardTo.Port) { + if backendRef.Port == nil || p.Port == int32(*backendRef.Port) { portSpec = p match = true break @@ -1299,7 +1483,7 @@ func loadServices(client Client, namespace string, targets []v1alpha1.HTTPRouteF return nil, nil, errors.New("service port not found") } - endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, pointer.StringDeref(forwardTo.ServiceName, "")) + endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, string(backendRef.Name)) if endpointsErr != nil { return nil, nil, endpointsErr } @@ -1350,7 +1534,7 @@ func loadServices(client Client, namespace string, targets []v1alpha1.HTTPRouteF } // loadTCPServices is generating a WRR service, even when there is only one target. -func loadTCPServices(client Client, namespace string, targets []v1alpha1.RouteForwardTo) (*dynamic.TCPService, map[string]*dynamic.TCPService, error) { +func loadTCPServices(client Client, namespace string, backendRefs []v1alpha2.BackendRef) (*dynamic.TCPService, map[string]*dynamic.TCPService, error) { services := map[string]*dynamic.TCPService{} wrrSvc := &dynamic.TCPService{ @@ -1359,31 +1543,32 @@ func loadTCPServices(client Client, namespace string, targets []v1alpha1.RouteFo }, } - for _, forwardTo := range targets { - weight := int(pointer.Int32Deref(forwardTo.Weight, 1)) - - if forwardTo.ServiceName == nil && forwardTo.BackendRef != nil { - if !(forwardTo.BackendRef.Group == traefikServiceGroupName && forwardTo.BackendRef.Kind == traefikServiceKind) { - continue - } - - if strings.HasSuffix(forwardTo.BackendRef.Name, "@internal") { - return nil, nil, fmt.Errorf("traefik internal service %s is not allowed in a TCP service", forwardTo.BackendRef.Name) - } - - wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.TCPWRRService{Name: forwardTo.BackendRef.Name, Weight: &weight}) + for _, backendRef := range backendRefs { + if backendRef.Group == nil || backendRef.Kind == nil { + // Should not happen as this is validated by kubernetes continue } - if forwardTo.ServiceName == nil { + if isInternalService(backendRef) { + return nil, nil, fmt.Errorf("traefik internal service %s is not allowed in a WRR loadbalancer", backendRef.Name) + } + + weight := int(pointer.Int32Deref(backendRef.Weight, 1)) + + if *backendRef.Group == traefikv1alpha1.GroupName && *backendRef.Kind == kindTraefikService { + wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.TCPWRRService{Name: string(backendRef.Name), Weight: &weight}) continue } + if *backendRef.Group != "" && *backendRef.Group != "core" && *backendRef.Kind != "Service" { + return nil, nil, fmt.Errorf("unsupported BackendRef %s/%s/%s", *backendRef.Group, *backendRef.Kind, backendRef.Name) + } + svc := dynamic.TCPService{ LoadBalancer: &dynamic.TCPServersLoadBalancer{}, } - service, exists, err := client.GetService(namespace, *forwardTo.ServiceName) + service, exists, err := client.GetService(namespace, string(backendRef.Name)) if err != nil { return nil, nil, err } @@ -1392,7 +1577,7 @@ func loadTCPServices(client Client, namespace string, targets []v1alpha1.RouteFo return nil, nil, errors.New("service not found") } - if len(service.Spec.Ports) > 1 && forwardTo.Port == nil { + if len(service.Spec.Ports) > 1 && backendRef.Port == nil { // If the port is unspecified and the backend is a Service // object consisting of multiple port definitions, the route // must be dropped from the Gateway. The controller should @@ -1400,7 +1585,7 @@ func loadTCPServices(client Client, namespace string, targets []v1alpha1.RouteFo // "DroppedRoutes" reason. The gateway status for this route // should be updated with a condition that describes the error // more specifically. - log.WithoutContext().Errorf("A multiple ports Kubernetes Service cannot be used if unspecified forwardTo.Port") + log.WithoutContext().Errorf("A multiple ports Kubernetes Service cannot be used if unspecified backendRef.Port") continue } @@ -1408,7 +1593,7 @@ func loadTCPServices(client Client, namespace string, targets []v1alpha1.RouteFo var match bool for _, p := range service.Spec.Ports { - if forwardTo.Port == nil || p.Port == int32(*forwardTo.Port) { + if backendRef.Port == nil || p.Port == int32(*backendRef.Port) { portSpec = p match = true break @@ -1419,7 +1604,7 @@ func loadTCPServices(client Client, namespace string, targets []v1alpha1.RouteFo return nil, nil, errors.New("service port not found") } - endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, *forwardTo.ServiceName) + endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, string(backendRef.Name)) if endpointsErr != nil { return nil, nil, endpointsErr } @@ -1506,10 +1691,12 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *s return eventsChanBuffered } -func isInternalService(forwardTo v1alpha1.HTTPRouteForwardTo) bool { - return forwardTo.ServiceName == nil && - forwardTo.BackendRef != nil && - forwardTo.BackendRef.Kind == traefikServiceKind && - forwardTo.BackendRef.Group == traefikServiceGroupName && - strings.HasSuffix(forwardTo.BackendRef.Name, "@internal") +func isInternalService(ref v1alpha2.BackendRef) bool { + if ref.Kind == nil || ref.Group == nil { + return false + } + + return *ref.Kind == kindTraefikService && + *ref.Group == traefikv1alpha1.GroupName && + strings.HasSuffix(string(ref.Name), "@internal") } diff --git a/pkg/provider/kubernetes/gateway/kubernetes_test.go b/pkg/provider/kubernetes/gateway/kubernetes_test.go index f972df5e2..2fafd65bb 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes_test.go +++ b/pkg/provider/kubernetes/gateway/kubernetes_test.go @@ -9,16 +9,13 @@ import ( "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/tls" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/pointer" - "sigs.k8s.io/gateway-api/apis/v1alpha1" + "sigs.k8s.io/gateway-api/apis/v1alpha2" ) var _ provider.Provider = (*Provider)(nil) -func PMT(p v1alpha1.PathMatchType) *v1alpha1.PathMatchType { return &p } - -func HMT(h v1alpha1.HeaderMatchType) *v1alpha1.HeaderMatchType { return &h } - func TestLoadHTTPRoutes(t *testing.T) { testCases := []struct { desc string @@ -124,7 +121,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, { - desc: "Empty caused by unknown GatewayClass controller name", + desc: "Empty caused by unknown GatewayClass controller desc", entryPoints: map[string]Entrypoint{"web": { Address: ":80", }}, @@ -149,7 +146,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, { - desc: "Empty caused by multiport service with wrong TargetPort", + desc: "Empty caused by multi ports service with wrong TargetPort", entryPoints: map[string]Entrypoint{"web": { Address: ":80", }}, @@ -484,7 +481,32 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, { - desc: "Simple HTTPRoute, with foo entrypoint", + desc: "Empty caused by HTTPRoute with TLS configuration", + entryPoints: map[string]Entrypoint{"web": { + Address: ":80", + }}, + paths: []string{"services.yml", "httproute/with_tls_configuration.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "Simple HTTPRoute", paths: []string{"services.yml", "httproute/simple.yml"}, entryPoints: map[string]Entrypoint{"web": { Address: ":80", @@ -821,15 +843,15 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-a431b128267aabc954fd": { + "default-http-app-1-my-gateway-web-eb1490f180299bf5ed29": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-a431b128267aabc954fd-wrr", - Rule: "PathPrefix(`/`)", + Service: "default-http-app-1-my-gateway-web-eb1490f180299bf5ed29-wrr", + Rule: "(Host(`foo.com`) || HostRegexp(`{subdomain:[a-zA-Z0-9-]+}.foo.com`)) && PathPrefix(`/`)", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-a431b128267aabc954fd-wrr": { + "default-http-app-1-my-gateway-web-eb1490f180299bf5ed29-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1201,10 +1223,10 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-6211a6376ce8f78494a8": { + "default-http-app-1-my-gateway-web-330d644a7f2079e8f454": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-6211a6376ce8f78494a8-wrr", - Rule: "Host(`foo.com`) && PathPrefix(`/bar`) && Headers(`my-header2`,`bar`) && Headers(`my-header`,`foo`)", + Service: "default-http-app-1-my-gateway-web-330d644a7f2079e8f454-wrr", + Rule: "Host(`foo.com`) && PathPrefix(`/bar`) && Headers(`my-header`,`foo`) && Headers(`my-header2`,`bar`)", }, "default-http-app-1-my-gateway-web-fe80e69a38713941ea22": { EntryPoints: []string{"web"}, @@ -1214,7 +1236,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-6211a6376ce8f78494a8-wrr": { + "default-http-app-1-my-gateway-web-330d644a7f2079e8f454-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1392,7 +1414,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, { - desc: "HTTPRoute with Selector Route Binding", + desc: "HTTPRoute with namespace selector", paths: []string{"services.yml", "httproute/with_namespace_selector.yml"}, entryPoints: map[string]Entrypoint{ "web": {Address: ":80"}, @@ -1450,7 +1472,6 @@ func TestLoadHTTPRoutes(t *testing.T) { for _, test := range testCases { test := test - t.Run(test.desc, func(t *testing.T) { t.Parallel() @@ -1570,7 +1591,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, { - desc: "Empty caused by unknown GatewayClass controller name", + desc: "Empty caused by unknown GatewayClass controller desc", entryPoints: map[string]Entrypoint{"TCP": { Address: ":8080", }}, @@ -1595,7 +1616,32 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, { - desc: "Empty caused by multiport service with wrong TargetPort", + desc: "Empty caused by HTTPRoute with TLS configuration", + entryPoints: map[string]Entrypoint{"web": { + Address: ":8080", + }}, + paths: []string{"services.yml", "tcproute/with_tls_configuration.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "Empty caused by multi ports service with wrong TargetPort", entryPoints: map[string]Entrypoint{"TCP": { Address: ":8080", }}, @@ -1620,7 +1666,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, { - desc: "Simple TCPRoute, with foo entrypoint", + desc: "Simple TCPRoute", paths: []string{"services.yml", "tcproute/simple.yml"}, entryPoints: map[string]Entrypoint{ "tcp": {Address: ":9000"}, @@ -1634,13 +1680,13 @@ func TestLoadTCPRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tcp-app-1-my-tcp-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-1-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-1-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -1674,7 +1720,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, { - desc: "Multiple TCPRoute, with foo entrypoint", + desc: "Multiple TCPRoute", paths: []string{"services.yml", "tcproute/with_multiple_routes.yml"}, entryPoints: map[string]Entrypoint{ "tcp-1": {Address: ":9000"}, @@ -1690,18 +1736,18 @@ func TestLoadTCPRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tcp-app-1-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp-1"}, - Service: "default-tcp-app-1-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-1-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, "default-tcp-app-2-my-tcp-gateway-tcp-2-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp-2"}, - Service: "default-tcp-app-2-my-tcp-gateway-tcp-2-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-2-my-tcp-gateway-tcp-2-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-1-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -1711,7 +1757,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, - "default-tcp-app-2-my-tcp-gateway-tcp-2-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-2-my-tcp-gateway-tcp-2-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -1757,7 +1803,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, { - desc: "Empty caused by TCPRoute with multiple rules", + desc: "TCPRoute with multiple rules", paths: []string{"services.yml", "tcproute/with_multiple_rules.yml"}, entryPoints: map[string]Entrypoint{ "tcp-1": {Address: ":9000"}, @@ -1770,9 +1816,74 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, + Routers: map[string]*dynamic.TCPRouter{ + "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb": { + EntryPoints: []string{"tcp-1"}, + Service: "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr", + Rule: "HostSNI(`*`)", + }, + }, Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Services: map[string]*dynamic.TCPService{ + "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr": { + Weighted: &dynamic.TCPWeightedRoundRobin{ + Services: []dynamic.TCPWRRService{ + { + Name: "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr-0", + Weight: func(i int) *int { return &i }(1), + }, + { + Name: "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr-1", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr-0": { + Weighted: &dynamic.TCPWeightedRoundRobin{ + Services: []dynamic.TCPWRRService{ + { + Name: "default-whoamitcp-9000", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr-1": { + Weighted: &dynamic.TCPWeightedRoundRobin{ + Services: []dynamic.TCPWRRService{ + { + Name: "default-whoamitcp-10000", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-whoamitcp-9000": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.9:9000", + }, + { + Address: "10.10.0.10:9000", + }, + }, + }, + }, + "default-whoamitcp-10000": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.9:10000", + }, + { + Address: "10.10.0.10:10000", + }, + }, + }, + }, + }, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1798,13 +1909,13 @@ func TestLoadTCPRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -1856,14 +1967,14 @@ func TestLoadTCPRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", TLS: &dynamic.RouterTCPTLSConfig{}, }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{{ Name: "default-whoamitcp-9000", @@ -1918,13 +2029,13 @@ func TestLoadTCPRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -1972,18 +2083,18 @@ func TestLoadTCPRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr", + Service: "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -1993,7 +2104,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr": { + "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2039,7 +2150,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, { - desc: "TCPRoute with Selector Route Binding", + desc: "TCPRoute with namespace selector", paths: []string{"services.yml", "tcproute/with_namespace_selector.yml"}, entryPoints: map[string]Entrypoint{ "tcp": {Address: ":9000"}, @@ -2053,13 +2164,13 @@ func TestLoadTCPRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr", + Service: "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr": { + "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2096,7 +2207,6 @@ func TestLoadTCPRoutes(t *testing.T) { for _, test := range testCases { test := test - t.Run(test.desc, func(t *testing.T) { t.Parallel() @@ -2216,7 +2326,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, { - desc: "Empty caused by unknown GatewayClass controller name", + desc: "Empty caused by unknown GatewayClass controller desc", entryPoints: map[string]Entrypoint{"TCP": { Address: ":8080", }}, @@ -2241,7 +2351,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, { - desc: "Empty caused by multiport service with wrong TargetPort", + desc: "Empty caused by multi ports service with wrong TargetPort", entryPoints: map[string]Entrypoint{"TCP": { Address: ":8080", }}, @@ -2266,7 +2376,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, { - desc: "Empty caused by mixed routes wrong selector", + desc: "Empty caused by mixed routes with wrong parent ref", entryPoints: map[string]Entrypoint{ "tcp": { Address: ":9000", @@ -2298,31 +2408,6 @@ func TestLoadTLSRoutes(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, - { - desc: "Empty caused by TLSRoute using a certificateRef", - entryPoints: map[string]Entrypoint{"TCP": { - Address: ":9000", - }}, - paths: []string{"services.yml", "tlsroute/simple_TLS_to_TCPRoute_with_certificateRef.yml"}, - expected: &dynamic.Configuration{ - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - TLS: &dynamic.TLSConfiguration{}, - }, - }, { desc: "Empty caused by simple TLSRoute with invalid SNI matching", paths: []string{"services.yml", "tlsroute/with_invalid_SNI_matching.yml"}, @@ -2349,7 +2434,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, { - desc: "Simple TLS listener to TCPRoute, with foo entrypoint", + desc: "Simple TLS listener to TCPRoute in Terminate mode", paths: []string{"services.yml", "tlsroute/simple_TLS_to_TCPRoute.yml"}, entryPoints: map[string]Entrypoint{ "tcp": {Address: ":9000"}, @@ -2363,14 +2448,14 @@ func TestLoadTLSRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", TLS: &dynamic.RouterTCPTLSConfig{}, }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2413,8 +2498,8 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, { - desc: "Simple TLS listener to TLSRoute", - paths: []string{"services.yml", "tlsroute/simple_TLS_to_TLSRoute.yml"}, + desc: "Simple TLS listener to TCPRoute in Passthrough mode", + paths: []string{"services.yml", "tlsroute/simple_TLS_to_TCPRoute_passthrough.yml"}, entryPoints: map[string]Entrypoint{ "tcp": {Address: ":9000"}, }, @@ -2425,9 +2510,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-tls-gateway-tcp-673acf455cb2dab0b43a": { + "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tls-app-1-my-tls-gateway-tcp-673acf455cb2dab0b43a-wrr", + Service: "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, @@ -2436,7 +2521,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-tls-gateway-tcp-673acf455cb2dab0b43a-wrr": { + "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2470,7 +2555,64 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, { - desc: "Multiple TLSRoute, with foo entrypoint", + desc: "Simple TLS listener to TLSRoute", + paths: []string{"services.yml", "tlsroute/simple_TLS_to_TLSRoute.yml"}, + entryPoints: map[string]Entrypoint{ + "tcp": {Address: ":9000"}, + }, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "default-tls-app-1-my-tls-gateway-tcp-f0dd0dd89f82eae1c270": { + EntryPoints: []string{"tcp"}, + Service: "default-tls-app-1-my-tls-gateway-tcp-f0dd0dd89f82eae1c270-wrr-0", + Rule: "HostSNI(`foo.example.com`)", + TLS: &dynamic.RouterTCPTLSConfig{ + Passthrough: true, + }, + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{ + "default-tls-app-1-my-tls-gateway-tcp-f0dd0dd89f82eae1c270-wrr-0": { + Weighted: &dynamic.TCPWeightedRoundRobin{ + Services: []dynamic.TCPWRRService{ + { + Name: "default-whoamitcp-9000", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-whoamitcp-9000": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.9:9000", + }, + { + Address: "10.10.0.10:9000", + }, + }, + }, + }, + }, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "Multiple TLSRoute", paths: []string{"services.yml", "tlsroute/with_multiple_routes_kind.yml"}, entryPoints: map[string]Entrypoint{ "tls": {Address: ":9000"}, @@ -2485,13 +2627,13 @@ func TestLoadTLSRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tcp-app-1-my-tls-gateway-tls-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-1-my-tls-gateway-tls-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-1-my-tls-gateway-tls-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", TLS: &dynamic.RouterTCPTLSConfig{}, }, "default-tls-app-1-my-tls-gateway-tcp-673acf455cb2dab0b43a": { EntryPoints: []string{"tcp"}, - Service: "default-tls-app-1-my-tls-gateway-tcp-673acf455cb2dab0b43a-wrr", + Service: "default-tls-app-1-my-tls-gateway-tcp-673acf455cb2dab0b43a-wrr-0", Rule: "HostSNI(`*`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, @@ -2500,7 +2642,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tls-gateway-tls-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-1-my-tls-gateway-tls-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2510,7 +2652,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, - "default-tls-app-1-my-tls-gateway-tcp-673acf455cb2dab0b43a-wrr": { + "default-tls-app-1-my-tls-gateway-tcp-673acf455cb2dab0b43a-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2579,14 +2721,14 @@ func TestLoadTLSRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", TLS: &dynamic.RouterTCPTLSConfig{}, }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2645,10 +2787,10 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-gateway-tls-673acf455cb2dab0b43a": { + "default-tls-app-1-my-gateway-tls-f0dd0dd89f82eae1c270": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-1-my-gateway-tls-673acf455cb2dab0b43a-wrr", - Rule: "HostSNI(`*`)", + Service: "default-tls-app-1-my-gateway-tls-f0dd0dd89f82eae1c270-wrr-0", + Rule: "HostSNI(`foo.example.com`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, }, @@ -2656,7 +2798,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-gateway-tls-673acf455cb2dab0b43a-wrr": { + "default-tls-app-1-my-gateway-tls-f0dd0dd89f82eae1c270-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2702,10 +2844,10 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-gateway-tls-673acf455cb2dab0b43a": { + "default-tls-app-1-my-gateway-tls-f0dd0dd89f82eae1c270": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-1-my-gateway-tls-673acf455cb2dab0b43a-wrr", - Rule: "HostSNI(`*`)", + Service: "default-tls-app-1-my-gateway-tls-f0dd0dd89f82eae1c270-wrr-0", + Rule: "HostSNI(`foo.example.com`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, }, @@ -2713,7 +2855,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-gateway-tls-673acf455cb2dab0b43a-wrr": { + "default-tls-app-1-my-gateway-tls-f0dd0dd89f82eae1c270-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2759,10 +2901,10 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-gateway-tls-2279fe75c5156dc5eb26": { + "default-tls-app-1-my-gateway-tls-f0dd0dd89f82eae1c270": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-1-my-gateway-tls-2279fe75c5156dc5eb26-wrr", - Rule: "HostSNI(`foo.bar`)", + Service: "default-tls-app-1-my-gateway-tls-f0dd0dd89f82eae1c270-wrr-0", + Rule: "HostSNI(`foo.example.com`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, }, @@ -2770,7 +2912,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-gateway-tls-2279fe75c5156dc5eb26-wrr": { + "default-tls-app-1-my-gateway-tls-f0dd0dd89f82eae1c270-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2816,10 +2958,10 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-gateway-tls-177bd313b8e78ce821eb": { + "default-tls-app-1-my-gateway-tls-339184c3296a9c2c39fa": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-1-my-gateway-tls-177bd313b8e78ce821eb-wrr", - Rule: "HostSNI(`foo.bar`,`fiz.baz`)", + Service: "default-tls-app-1-my-gateway-tls-339184c3296a9c2c39fa-wrr-0", + Rule: "HostSNI(`foo.example.com`,`bar.example.com`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, }, @@ -2827,7 +2969,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-gateway-tls-177bd313b8e78ce821eb-wrr": { + "default-tls-app-1-my-gateway-tls-339184c3296a9c2c39fa-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2875,7 +3017,7 @@ func TestLoadTLSRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tls-app-default-my-gateway-tls-06ae57dcf13ab4c60ee5": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-default-my-gateway-tls-06ae57dcf13ab4c60ee5-wrr", + Service: "default-tls-app-default-my-gateway-tls-06ae57dcf13ab4c60ee5-wrr-0", Rule: "HostSNI(`foo.default`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, @@ -2884,7 +3026,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-default-my-gateway-tls-06ae57dcf13ab4c60ee5-wrr": { + "default-tls-app-default-my-gateway-tls-06ae57dcf13ab4c60ee5-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2932,7 +3074,7 @@ func TestLoadTLSRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tls-app-default-my-gateway-tls-06ae57dcf13ab4c60ee5": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-default-my-gateway-tls-06ae57dcf13ab4c60ee5-wrr", + Service: "default-tls-app-default-my-gateway-tls-06ae57dcf13ab4c60ee5-wrr-0", Rule: "HostSNI(`foo.default`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, @@ -2940,7 +3082,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, "bar-tls-app-bar-my-gateway-tls-2279fe75c5156dc5eb26": { EntryPoints: []string{"tls"}, - Service: "bar-tls-app-bar-my-gateway-tls-2279fe75c5156dc5eb26-wrr", + Service: "bar-tls-app-bar-my-gateway-tls-2279fe75c5156dc5eb26-wrr-0", Rule: "HostSNI(`foo.bar`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, @@ -2949,7 +3091,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-default-my-gateway-tls-06ae57dcf13ab4c60ee5-wrr": { + "default-tls-app-default-my-gateway-tls-06ae57dcf13ab4c60ee5-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2959,7 +3101,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, - "bar-tls-app-bar-my-gateway-tls-2279fe75c5156dc5eb26-wrr": { + "bar-tls-app-bar-my-gateway-tls-2279fe75c5156dc5eb26-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3005,7 +3147,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, { - desc: "TLSRoute with Selector Route Binding", + desc: "TLSRoute with namespace selector", paths: []string{"services.yml", "tlsroute/with_namespace_selector.yml"}, entryPoints: map[string]Entrypoint{ "tls": {Address: ":9001"}, @@ -3019,7 +3161,7 @@ func TestLoadTLSRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "bar-tls-app-bar-my-gateway-tls-2279fe75c5156dc5eb26": { EntryPoints: []string{"tls"}, - Service: "bar-tls-app-bar-my-gateway-tls-2279fe75c5156dc5eb26-wrr", + Service: "bar-tls-app-bar-my-gateway-tls-2279fe75c5156dc5eb26-wrr-0", Rule: "HostSNI(`foo.bar`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, @@ -3028,7 +3170,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "bar-tls-app-bar-my-gateway-tls-2279fe75c5156dc5eb26-wrr": { + "bar-tls-app-bar-my-gateway-tls-2279fe75c5156dc5eb26-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3061,11 +3203,103 @@ func TestLoadTLSRoutes(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, + { + desc: "TLSRoute with multiple rules", + paths: []string{"services.yml", "tlsroute/with_multiple_rules.yml"}, + entryPoints: map[string]Entrypoint{ + "tcp-1": {Address: ":9000"}, + }, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "default-tls-app-my-gateway-tcp-1-673acf455cb2dab0b43a": { + EntryPoints: []string{"tcp-1"}, + Service: "default-tls-app-my-gateway-tcp-1-673acf455cb2dab0b43a-wrr", + Rule: "HostSNI(`*`)", + TLS: &dynamic.RouterTCPTLSConfig{ + Passthrough: true, + }, + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{ + "default-tls-app-my-gateway-tcp-1-673acf455cb2dab0b43a-wrr": { + Weighted: &dynamic.TCPWeightedRoundRobin{ + Services: []dynamic.TCPWRRService{ + { + Name: "default-tls-app-my-gateway-tcp-1-673acf455cb2dab0b43a-wrr-0", + Weight: func(i int) *int { return &i }(1), + }, + { + Name: "default-tls-app-my-gateway-tcp-1-673acf455cb2dab0b43a-wrr-1", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-tls-app-my-gateway-tcp-1-673acf455cb2dab0b43a-wrr-0": { + Weighted: &dynamic.TCPWeightedRoundRobin{ + Services: []dynamic.TCPWRRService{ + { + Name: "default-whoamitcp-9000", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-tls-app-my-gateway-tcp-1-673acf455cb2dab0b43a-wrr-1": { + Weighted: &dynamic.TCPWeightedRoundRobin{ + Services: []dynamic.TCPWRRService{ + { + Name: "default-whoamitcp-10000", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-whoamitcp-9000": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.9:9000", + }, + { + Address: "10.10.0.10:9000", + }, + }, + }, + }, + "default-whoamitcp-10000": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.9:10000", + }, + { + Address: "10.10.0.10:10000", + }, + }, + }, + }, + }, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, } for _, test := range testCases { test := test - t.Run(test.desc, func(t *testing.T) { t.Parallel() @@ -3203,19 +3437,19 @@ func TestLoadMixedRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, "default-tcp-app-1-my-gateway-tls-1-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-1"}, - Service: "default-tcp-app-1-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-1-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", TLS: &dynamic.RouterTCPTLSConfig{}, }, - "default-tls-app-1-my-gateway-tls-2-673acf455cb2dab0b43a": { + "default-tls-app-1-my-gateway-tls-2-59130f7db6718b7700c1": { EntryPoints: []string{"tls-2"}, - Service: "default-tls-app-1-my-gateway-tls-2-673acf455cb2dab0b43a-wrr", - Rule: "HostSNI(`*`)", + Service: "default-tls-app-1-my-gateway-tls-2-59130f7db6718b7700c1-wrr-0", + Rule: "HostSNI(`pass.tls.foo.example.com`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, }, @@ -3223,7 +3457,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3233,7 +3467,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tcp-app-1-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-1-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3243,7 +3477,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tls-app-1-my-gateway-tls-2-673acf455cb2dab0b43a-wrr": { + "default-tls-app-1-my-gateway-tls-2-59130f7db6718b7700c1-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3377,19 +3611,19 @@ func TestLoadMixedRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-1"}, - Service: "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", TLS: &dynamic.RouterTCPTLSConfig{}, }, - "default-tls-app-default-my-gateway-tls-2-673acf455cb2dab0b43a": { + "default-tls-app-default-my-gateway-tls-2-59130f7db6718b7700c1": { EntryPoints: []string{"tls-2"}, - Service: "default-tls-app-default-my-gateway-tls-2-673acf455cb2dab0b43a-wrr", - Rule: "HostSNI(`*`)", + Service: "default-tls-app-default-my-gateway-tls-2-59130f7db6718b7700c1-wrr-0", + Rule: "HostSNI(`pass.tls.foo.example.com`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, }, @@ -3397,7 +3631,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3407,7 +3641,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3417,7 +3651,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tls-app-default-my-gateway-tls-2-673acf455cb2dab0b43a-wrr": { + "default-tls-app-default-my-gateway-tls-2-59130f7db6718b7700c1-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3524,38 +3758,38 @@ func TestLoadMixedRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-1"}, - Service: "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", TLS: &dynamic.RouterTCPTLSConfig{}, }, - "default-tls-app-default-my-gateway-tls-2-673acf455cb2dab0b43a": { + "default-tls-app-default-my-gateway-tls-2-59130f7db6718b7700c1": { EntryPoints: []string{"tls-2"}, - Service: "default-tls-app-default-my-gateway-tls-2-673acf455cb2dab0b43a-wrr", - Rule: "HostSNI(`*`)", + Service: "default-tls-app-default-my-gateway-tls-2-59130f7db6718b7700c1-wrr-0", + Rule: "HostSNI(`pass.tls.foo.example.com`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, }, }, "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb-wrr", + Service: "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-1"}, - Service: "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr", + Service: "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", TLS: &dynamic.RouterTCPTLSConfig{}, }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3565,7 +3799,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3575,7 +3809,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tls-app-default-my-gateway-tls-2-673acf455cb2dab0b43a-wrr": { + "default-tls-app-default-my-gateway-tls-2-59130f7db6718b7700c1-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3609,7 +3843,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb-wrr": { + "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3619,7 +3853,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr": { + "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3758,19 +3992,19 @@ func TestLoadMixedRoutes(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb-wrr", + Service: "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", }, "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-1"}, - Service: "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr", + Service: "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0", Rule: "HostSNI(`*`)", TLS: &dynamic.RouterTCPTLSConfig{}, }, - "bar-tls-app-bar-my-gateway-tls-2-673acf455cb2dab0b43a": { + "bar-tls-app-bar-my-gateway-tls-2-59130f7db6718b7700c1": { EntryPoints: []string{"tls-2"}, - Service: "bar-tls-app-bar-my-gateway-tls-2-673acf455cb2dab0b43a-wrr", - Rule: "HostSNI(`*`)", + Service: "bar-tls-app-bar-my-gateway-tls-2-59130f7db6718b7700c1-wrr-0", + Rule: "HostSNI(`pass.tls.foo.example.com`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, }, @@ -3790,7 +4024,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb-wrr": { + "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3800,7 +4034,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr": { + "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3810,7 +4044,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tls-app-bar-my-gateway-tls-2-673acf455cb2dab0b43a-wrr": { + "bar-tls-app-bar-my-gateway-tls-2-59130f7db6718b7700c1-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3886,11 +4120,138 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, + { + desc: "Mixed routes with core group", + paths: []string{"services.yml", "mixed/with_core_group.yml"}, + entryPoints: map[string]Entrypoint{ + "web": {Address: ":9080"}, + "websecure": {Address: ":9443"}, + "tcp": {Address: ":9000"}, + "tls": {Address: ":10000"}, + }, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb": { + EntryPoints: []string{"tcp"}, + Service: "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Rule: "HostSNI(`*`)", + }, + "default-tcp-app-default-my-gateway-tls-e3b0c44298fc1c149afb": { + EntryPoints: []string{"tls"}, + Service: "default-tcp-app-default-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0", + Rule: "HostSNI(`*`)", + TLS: &dynamic.RouterTCPTLSConfig{}, + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{ + "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + Weighted: &dynamic.TCPWeightedRoundRobin{ + Services: []dynamic.TCPWRRService{ + { + Name: "default-whoamitcp-9000", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-tcp-app-default-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0": { + Weighted: &dynamic.TCPWeightedRoundRobin{ + Services: []dynamic.TCPWRRService{ + { + Name: "default-whoamitcp-9000", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-whoamitcp-9000": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.9:9000", + }, + { + Address: "10.10.0.10:9000", + }, + }, + }, + }, + }, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "default-http-app-default-my-gateway-web-a431b128267aabc954fd": { + EntryPoints: []string{"web"}, + Service: "default-http-app-default-my-gateway-web-a431b128267aabc954fd-wrr", + Rule: "PathPrefix(`/`)", + }, + "default-http-app-default-my-gateway-websecure-a431b128267aabc954fd": { + EntryPoints: []string{"websecure"}, + Service: "default-http-app-default-my-gateway-websecure-a431b128267aabc954fd-wrr", + Rule: "PathPrefix(`/`)", + TLS: &dynamic.RouterTLSConfig{}, + }, + }, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{ + "default-http-app-default-my-gateway-web-a431b128267aabc954fd-wrr": { + Weighted: &dynamic.WeightedRoundRobin{ + Services: []dynamic.WRRService{ + { + Name: "default-whoami-80", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-http-app-default-my-gateway-websecure-a431b128267aabc954fd-wrr": { + Weighted: &dynamic.WeightedRoundRobin{ + Services: []dynamic.WRRService{ + { + Name: "default-whoami-80", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-whoami-80": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.1:80", + }, + { + URL: "http://10.10.0.2:80", + }, + }, + PassHostHeader: pointer.Bool(true), + }, + }, + }, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{ + Certificates: []*tls.CertAndStores{ + { + Certificate: tls.Certificate{ + CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"), + }, + }, + }, + }, + }, + }, } for _, test := range testCases { test := test - t.Run(test.desc, func(t *testing.T) { t.Parallel() @@ -3905,10 +4266,10 @@ func TestLoadMixedRoutes(t *testing.T) { } } -func TestHostRule(t *testing.T) { +func Test_hostRule(t *testing.T) { testCases := []struct { desc string - routeSpec v1alpha1.HTTPRouteSpec + hostnames []v1alpha2.Hostname expectedRule string expectErr bool }{ @@ -3918,102 +4279,82 @@ func TestHostRule(t *testing.T) { }, { desc: "One Host", - routeSpec: v1alpha1.HTTPRouteSpec{ - Hostnames: []v1alpha1.Hostname{ - "Foo", - }, + hostnames: []v1alpha2.Hostname{ + "Foo", }, expectedRule: "Host(`Foo`)", }, { desc: "Multiple Hosts", - routeSpec: v1alpha1.HTTPRouteSpec{ - Hostnames: []v1alpha1.Hostname{ - "Foo", - "Bar", - "Bir", - }, + hostnames: []v1alpha2.Hostname{ + "Foo", + "Bar", + "Bir", }, expectedRule: "Host(`Foo`, `Bar`, `Bir`)", }, { desc: "Multiple Hosts with empty one", - routeSpec: v1alpha1.HTTPRouteSpec{ - Hostnames: []v1alpha1.Hostname{ - "Foo", - "", - "Bir", - }, + hostnames: []v1alpha2.Hostname{ + "Foo", + "", + "Bir", }, expectedRule: "", }, { desc: "Multiple empty hosts", - routeSpec: v1alpha1.HTTPRouteSpec{ - Hostnames: []v1alpha1.Hostname{ - "", - "", - "", - }, + hostnames: []v1alpha2.Hostname{ + "", + "", + "", }, expectedRule: "", }, { desc: "Several Host and wildcard", - routeSpec: v1alpha1.HTTPRouteSpec{ - Hostnames: []v1alpha1.Hostname{ - "*.bar.foo", - "bar.foo", - "foo.foo", - }, + hostnames: []v1alpha2.Hostname{ + "*.bar.foo", + "bar.foo", + "foo.foo", }, expectedRule: "(Host(`bar.foo`, `foo.foo`) || HostRegexp(`{subdomain:[a-zA-Z0-9-]+}.bar.foo`))", }, { desc: "Host with wildcard", - routeSpec: v1alpha1.HTTPRouteSpec{ - Hostnames: []v1alpha1.Hostname{ - "*.bar.foo", - }, + hostnames: []v1alpha2.Hostname{ + "*.bar.foo", }, expectedRule: "HostRegexp(`{subdomain:[a-zA-Z0-9-]+}.bar.foo`)", }, { desc: "Alone wildcard", - routeSpec: v1alpha1.HTTPRouteSpec{ - Hostnames: []v1alpha1.Hostname{ - "*", - "*.foo.foo", - }, + hostnames: []v1alpha2.Hostname{ + "*", + "*.foo.foo", }, }, { desc: "Multiple alone Wildcard", - routeSpec: v1alpha1.HTTPRouteSpec{ - Hostnames: []v1alpha1.Hostname{ - "foo.foo", - "*.*", - }, + hostnames: []v1alpha2.Hostname{ + "foo.foo", + "*.*", }, expectErr: true, }, { desc: "Multiple Wildcard", - routeSpec: v1alpha1.HTTPRouteSpec{ - Hostnames: []v1alpha1.Hostname{ - "foo.foo", - "*.toto.*.bar.foo", - }, + hostnames: []v1alpha2.Hostname{ + "foo.foo", + "*.toto.*.bar.foo", }, expectErr: true, }, { desc: "Multiple subdomain with misplaced wildcard", - routeSpec: v1alpha1.HTTPRouteSpec{ - Hostnames: []v1alpha1.Hostname{ - "foo.foo", - "toto.*.bar.foo", - }, + hostnames: []v1alpha2.Hostname{ + "foo.foo", + "toto.*.bar.foo", }, expectErr: true, }, @@ -4023,7 +4364,7 @@ func TestHostRule(t *testing.T) { test := test t.Run(test.desc, func(t *testing.T) { t.Parallel() - rule, err := hostRule(test.routeSpec) + rule, err := hostRule(test.hostnames) assert.Equal(t, test.expectedRule, rule) if test.expectErr { @@ -4033,10 +4374,10 @@ func TestHostRule(t *testing.T) { } } -func TestExtractRule(t *testing.T) { +func Test_extractRule(t *testing.T) { testCases := []struct { desc string - routeRule v1alpha1.HTTPRouteRule + routeRule v1alpha2.HTTPRouteRule hostRule string expectedRule string expectedError bool @@ -4052,8 +4393,8 @@ func TestExtractRule(t *testing.T) { }, { desc: "One HTTPRouteMatch with nil HTTPHeaderMatch", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ + routeRule: v1alpha2.HTTPRouteRule{ + Matches: []v1alpha2.HTTPRouteMatch{ {Headers: nil}, }, }, @@ -4061,26 +4402,11 @@ func TestExtractRule(t *testing.T) { }, { desc: "One HTTPRouteMatch with nil HTTPHeaderMatch Type", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ + routeRule: v1alpha2.HTTPRouteRule{ + Matches: []v1alpha2.HTTPRouteMatch{ { - Headers: &v1alpha1.HTTPHeaderMatch{ - Type: nil, - Values: map[string]string{"foo": "bar"}, - }, - }, - }, - }, - expectedRule: "", - }, - { - desc: "One HTTPRouteMatch with nil HTTPHeaderMatch Values", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ - { - Headers: &v1alpha1.HTTPHeaderMatch{ - Type: HMT(v1alpha1.HeaderMatchExact), - Values: nil, + Headers: []v1alpha2.HTTPHeaderMatch{ + {Type: nil, Name: "foo", Value: "bar"}, }, }, }, @@ -4089,8 +4415,8 @@ func TestExtractRule(t *testing.T) { }, { desc: "One HTTPRouteMatch with nil HTTPPathMatch", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ + routeRule: v1alpha2.HTTPRouteRule{ + Matches: []v1alpha2.HTTPRouteMatch{ {Path: nil}, }, }, @@ -4098,10 +4424,10 @@ func TestExtractRule(t *testing.T) { }, { desc: "One HTTPRouteMatch with nil HTTPPathMatch Type", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ + routeRule: v1alpha2.HTTPRouteRule{ + Matches: []v1alpha2.HTTPRouteMatch{ { - Path: &v1alpha1.HTTPPathMatch{ + Path: &v1alpha2.HTTPPathMatch{ Type: nil, Value: pointer.String("/foo/"), }, @@ -4112,11 +4438,11 @@ func TestExtractRule(t *testing.T) { }, { desc: "One HTTPRouteMatch with nil HTTPPathMatch Values", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ + routeRule: v1alpha2.HTTPRouteRule{ + Matches: []v1alpha2.HTTPRouteMatch{ { - Path: &v1alpha1.HTTPPathMatch{ - Type: PMT(v1alpha1.PathMatchExact), + Path: &v1alpha2.HTTPPathMatch{ + Type: pathMatchTypePtr(v1alpha2.PathMatchExact), Value: nil, }, }, @@ -4126,11 +4452,11 @@ func TestExtractRule(t *testing.T) { }, { desc: "One Path in matches", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ + routeRule: v1alpha2.HTTPRouteRule{ + Matches: []v1alpha2.HTTPRouteMatch{ { - Path: &v1alpha1.HTTPPathMatch{ - Type: PMT(v1alpha1.PathMatchExact), + Path: &v1alpha2.HTTPPathMatch{ + Type: pathMatchTypePtr(v1alpha2.PathMatchExact), Value: pointer.String("/foo/"), }, }, @@ -4140,17 +4466,17 @@ func TestExtractRule(t *testing.T) { }, { desc: "One Path in matches and another unknown", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ + routeRule: v1alpha2.HTTPRouteRule{ + Matches: []v1alpha2.HTTPRouteMatch{ { - Path: &v1alpha1.HTTPPathMatch{ - Type: PMT(v1alpha1.PathMatchExact), + Path: &v1alpha2.HTTPPathMatch{ + Type: pathMatchTypePtr(v1alpha2.PathMatchExact), Value: pointer.String("/foo/"), }, }, { - Path: &v1alpha1.HTTPPathMatch{ - Type: PMT("unknown"), + Path: &v1alpha2.HTTPPathMatch{ + Type: pathMatchTypePtr("unknown"), Value: pointer.String("/foo/"), }, }, @@ -4160,11 +4486,11 @@ func TestExtractRule(t *testing.T) { }, { desc: "One Path in matches and another empty", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ + routeRule: v1alpha2.HTTPRouteRule{ + Matches: []v1alpha2.HTTPRouteMatch{ { - Path: &v1alpha1.HTTPPathMatch{ - Type: PMT(v1alpha1.PathMatchExact), + Path: &v1alpha2.HTTPPathMatch{ + Type: pathMatchTypePtr(v1alpha2.PathMatchExact), Value: pointer.String("/foo/"), }, }, @@ -4175,19 +4501,20 @@ func TestExtractRule(t *testing.T) { }, { desc: "Path OR Header rules", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ + routeRule: v1alpha2.HTTPRouteRule{ + Matches: []v1alpha2.HTTPRouteMatch{ { - Path: &v1alpha1.HTTPPathMatch{ - Type: PMT(v1alpha1.PathMatchExact), + Path: &v1alpha2.HTTPPathMatch{ + Type: pathMatchTypePtr(v1alpha2.PathMatchExact), Value: pointer.String("/foo/"), }, }, { - Headers: &v1alpha1.HTTPHeaderMatch{ - Type: HMT(v1alpha1.HeaderMatchExact), - Values: map[string]string{ - "my-header": "foo", + Headers: []v1alpha2.HTTPHeaderMatch{ + { + Type: headerMatchTypePtr(v1alpha2.HeaderMatchExact), + Name: "my-header", + Value: "foo", }, }, }, @@ -4197,17 +4524,18 @@ func TestExtractRule(t *testing.T) { }, { desc: "Path && Header rules", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ + routeRule: v1alpha2.HTTPRouteRule{ + Matches: []v1alpha2.HTTPRouteMatch{ { - Path: &v1alpha1.HTTPPathMatch{ - Type: PMT(v1alpha1.PathMatchExact), + Path: &v1alpha2.HTTPPathMatch{ + Type: pathMatchTypePtr(v1alpha2.PathMatchExact), Value: pointer.String("/foo/"), }, - Headers: &v1alpha1.HTTPHeaderMatch{ - Type: HMT(v1alpha1.HeaderMatchExact), - Values: map[string]string{ - "my-header": "foo", + Headers: []v1alpha2.HTTPHeaderMatch{ + { + Type: headerMatchTypePtr(v1alpha2.HeaderMatchExact), + Name: "my-header", + Value: "foo", }, }, }, @@ -4218,17 +4546,18 @@ func TestExtractRule(t *testing.T) { { desc: "Host && Path && Header rules", hostRule: "Host(`foo.com`)", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ + routeRule: v1alpha2.HTTPRouteRule{ + Matches: []v1alpha2.HTTPRouteMatch{ { - Path: &v1alpha1.HTTPPathMatch{ - Type: PMT(v1alpha1.PathMatchExact), + Path: &v1alpha2.HTTPPathMatch{ + Type: pathMatchTypePtr(v1alpha2.PathMatchExact), Value: pointer.String("/foo/"), }, - Headers: &v1alpha1.HTTPHeaderMatch{ - Type: HMT(v1alpha1.HeaderMatchExact), - Values: map[string]string{ - "my-header": "foo", + Headers: []v1alpha2.HTTPHeaderMatch{ + { + Type: headerMatchTypePtr(v1alpha2.HeaderMatchExact), + Name: "my-header", + Value: "foo", }, }, }, @@ -4239,19 +4568,20 @@ func TestExtractRule(t *testing.T) { { desc: "Host && (Path || Header) rules", hostRule: "Host(`foo.com`)", - routeRule: v1alpha1.HTTPRouteRule{ - Matches: []v1alpha1.HTTPRouteMatch{ + routeRule: v1alpha2.HTTPRouteRule{ + Matches: []v1alpha2.HTTPRouteMatch{ { - Path: &v1alpha1.HTTPPathMatch{ - Type: PMT(v1alpha1.PathMatchExact), + Path: &v1alpha2.HTTPPathMatch{ + Type: pathMatchTypePtr(v1alpha2.PathMatchExact), Value: pointer.String("/foo/"), }, }, { - Headers: &v1alpha1.HTTPHeaderMatch{ - Type: HMT(v1alpha1.HeaderMatchExact), - Values: map[string]string{ - "my-header": "foo", + Headers: []v1alpha2.HTTPHeaderMatch{ + { + Type: headerMatchTypePtr(v1alpha2.HeaderMatchExact), + Name: "my-header", + Value: "foo", }, }, }, @@ -4278,127 +4608,50 @@ func TestExtractRule(t *testing.T) { } } -func TestHostSNI(t *testing.T) { +func Test_hostSNIRule(t *testing.T) { testCases := []struct { desc string - routeRule v1alpha1.TLSRouteRule + hostnames []v1alpha2.Hostname expectedRule string expectError bool }{ { - desc: "Empty rule", + desc: "Empty", expectedRule: "HostSNI(`*`)", }, { - desc: "Empty rule and matches", - routeRule: v1alpha1.TLSRouteRule{ - Matches: []v1alpha1.TLSRouteMatch{}, - }, + desc: "Empty hostname", + hostnames: []v1alpha2.Hostname{""}, expectedRule: "HostSNI(`*`)", }, { - desc: "One match, SNI with empty hostname", - routeRule: v1alpha1.TLSRouteRule{ - Matches: []v1alpha1.TLSRouteMatch{ - { - SNIs: []v1alpha1.Hostname{""}, - }, - }, - }, - expectedRule: "HostSNI(`*`)", - }, - { - desc: "One match, SNI with one unsupported wildcard", - routeRule: v1alpha1.TLSRouteRule{ - Matches: []v1alpha1.TLSRouteMatch{ - { - SNIs: []v1alpha1.Hostname{"*"}, - }, - }, - }, + desc: "Unsupported wildcard", + hostnames: []v1alpha2.Hostname{"*"}, expectError: true, }, { - desc: "One match, SNI with multiple malformed wildcard", - routeRule: v1alpha1.TLSRouteRule{ - Matches: []v1alpha1.TLSRouteMatch{ - { - SNIs: []v1alpha1.Hostname{"*.foo.*"}, - }, - }, - }, + desc: "Multiple malformed wildcard", + hostnames: []v1alpha2.Hostname{"*.foo.*"}, expectError: true, }, { - desc: "One match, SNI with some empty hostnames", - routeRule: v1alpha1.TLSRouteRule{ - Matches: []v1alpha1.TLSRouteMatch{ - { - SNIs: []v1alpha1.Hostname{"foo", "", "bar"}, - }, - }, - }, + desc: "Some empty hostnames", + hostnames: []v1alpha2.Hostname{"foo", "", "bar"}, expectedRule: "HostSNI(`foo`,`bar`)", }, { - desc: "One match, one SNI hostname", - routeRule: v1alpha1.TLSRouteRule{ - Matches: []v1alpha1.TLSRouteMatch{ - { - SNIs: []v1alpha1.Hostname{"foo"}, - }, - }, - }, + desc: "Valid hostname", + hostnames: []v1alpha2.Hostname{"foo"}, expectedRule: "HostSNI(`foo`)", }, { - desc: "One match, multiple SNI hostnames", - routeRule: v1alpha1.TLSRouteRule{ - Matches: []v1alpha1.TLSRouteMatch{ - { - SNIs: []v1alpha1.Hostname{"foo", "bar"}, - }, - }, - }, + desc: "Multiple valid hostnames", + hostnames: []v1alpha2.Hostname{"foo", "bar"}, expectedRule: "HostSNI(`foo`,`bar`)", }, { - desc: "One SNI multiple hostnames", - routeRule: v1alpha1.TLSRouteRule{ - Matches: []v1alpha1.TLSRouteMatch{ - { - SNIs: []v1alpha1.Hostname{"foo", "bar"}, - }, - }, - }, - expectedRule: "HostSNI(`foo`,`bar`)", - }, - { - desc: "Multiple SNI multiple hostnames", - routeRule: v1alpha1.TLSRouteRule{ - Matches: []v1alpha1.TLSRouteMatch{ - { - SNIs: []v1alpha1.Hostname{"foo", "bar"}, - }, - { - SNIs: []v1alpha1.Hostname{"foz", "baz"}, - }, - }, - }, - expectedRule: "HostSNI(`foo`,`bar`,`foz`,`baz`)", - }, - { - desc: "Multiple SNI multiple hostnames overlapping", - routeRule: v1alpha1.TLSRouteRule{ - Matches: []v1alpha1.TLSRouteMatch{ - { - SNIs: []v1alpha1.Hostname{"foo", "bar"}, - }, - { - SNIs: []v1alpha1.Hostname{"foo", "baz"}, - }, - }, - }, + desc: "Multiple overlapping hostnames", + hostnames: []v1alpha2.Hostname{"foo", "bar", "foo", "baz"}, expectedRule: "HostSNI(`foo`,`bar`,`baz`)", }, } @@ -4408,7 +4661,7 @@ func TestHostSNI(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - rule, err := hostSNIRule(test.routeRule) + rule, err := hostSNIRule(test.hostnames) if test.expectError { assert.Error(t, err) return @@ -4419,3 +4672,564 @@ func TestHostSNI(t *testing.T) { }) } } + +func Test_shouldAttach(t *testing.T) { + testCases := []struct { + desc string + gateway *v1alpha2.Gateway + listener v1alpha2.Listener + routeNamespace string + routeSpec v1alpha2.CommonRouteSpec + expectedAttach bool + }{ + { + desc: "No ParentRefs", + gateway: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway", + Namespace: "default", + }, + }, + listener: v1alpha2.Listener{ + Name: "foo", + }, + routeNamespace: "default", + routeSpec: v1alpha2.CommonRouteSpec{ + ParentRefs: nil, + }, + expectedAttach: false, + }, + { + desc: "Unsupported Kind", + gateway: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway", + Namespace: "default", + }, + }, + listener: v1alpha2.Listener{ + Name: "foo", + }, + routeNamespace: "default", + routeSpec: v1alpha2.CommonRouteSpec{ + ParentRefs: []v1alpha2.ParentRef{ + { + SectionName: sectionNamePtr("bar"), + Name: "gateway", + Namespace: namespacePtr("default"), + Kind: kindPtr("Foo"), + Group: groupPtr(v1alpha2.GroupName), + }, + }, + }, + expectedAttach: false, + }, + { + desc: "Unsupported Group", + gateway: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway", + Namespace: "default", + }, + }, + listener: v1alpha2.Listener{ + Name: "foo", + }, + routeNamespace: "default", + routeSpec: v1alpha2.CommonRouteSpec{ + ParentRefs: []v1alpha2.ParentRef{ + { + SectionName: sectionNamePtr("bar"), + Name: "gateway", + Namespace: namespacePtr("default"), + Kind: kindPtr("Gateway"), + Group: groupPtr("foo.com"), + }, + }, + }, + expectedAttach: false, + }, + { + desc: "Kind is nil", + gateway: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway", + Namespace: "default", + }, + }, + listener: v1alpha2.Listener{ + Name: "foo", + }, + routeNamespace: "default", + routeSpec: v1alpha2.CommonRouteSpec{ + ParentRefs: []v1alpha2.ParentRef{ + { + SectionName: sectionNamePtr("bar"), + Name: "gateway", + Namespace: namespacePtr("default"), + Group: groupPtr(v1alpha2.GroupName), + }, + }, + }, + expectedAttach: false, + }, + { + desc: "Group is nil", + gateway: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway", + Namespace: "default", + }, + }, + listener: v1alpha2.Listener{ + Name: "foo", + }, + routeNamespace: "default", + routeSpec: v1alpha2.CommonRouteSpec{ + ParentRefs: []v1alpha2.ParentRef{ + { + SectionName: sectionNamePtr("bar"), + Name: "gateway", + Namespace: namespacePtr("default"), + Kind: kindPtr("Gateway"), + }, + }, + }, + expectedAttach: false, + }, + { + desc: "SectionName does not match a listener desc", + gateway: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway", + Namespace: "default", + }, + }, + listener: v1alpha2.Listener{ + Name: "foo", + }, + routeNamespace: "default", + routeSpec: v1alpha2.CommonRouteSpec{ + ParentRefs: []v1alpha2.ParentRef{ + { + SectionName: sectionNamePtr("bar"), + Name: "gateway", + Namespace: namespacePtr("default"), + Group: groupPtr(v1alpha2.GroupName), + Kind: kindPtr("Gateway"), + }, + }, + }, + expectedAttach: false, + }, + { + desc: "Namespace does not match the Gateway namespace", + gateway: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway", + Namespace: "default", + }, + }, + listener: v1alpha2.Listener{ + Name: "foo", + }, + routeNamespace: "default", + routeSpec: v1alpha2.CommonRouteSpec{ + ParentRefs: []v1alpha2.ParentRef{ + { + SectionName: sectionNamePtr("bar"), + Name: "gateway", + Namespace: namespacePtr("bar"), + Group: groupPtr(v1alpha2.GroupName), + Kind: kindPtr("Gateway"), + }, + }, + }, + expectedAttach: false, + }, + { + desc: "Route namespace does not match the Gateway namespace", + gateway: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway", + Namespace: "default", + }, + }, + listener: v1alpha2.Listener{ + Name: "foo", + }, + routeNamespace: "bar", + routeSpec: v1alpha2.CommonRouteSpec{ + ParentRefs: []v1alpha2.ParentRef{ + { + SectionName: sectionNamePtr("bar"), + Name: "gateway", + Group: groupPtr(v1alpha2.GroupName), + Kind: kindPtr("Gateway"), + }, + }, + }, + expectedAttach: false, + }, + { + desc: "Unsupported Kind", + gateway: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway", + Namespace: "default", + }, + }, + listener: v1alpha2.Listener{ + Name: "foo", + }, + routeNamespace: "default", + routeSpec: v1alpha2.CommonRouteSpec{ + ParentRefs: []v1alpha2.ParentRef{ + { + SectionName: sectionNamePtr("bar"), + Name: "gateway", + Namespace: namespacePtr("default"), + Kind: kindPtr("Gateway"), + Group: groupPtr(v1alpha2.GroupName), + }, + }, + }, + expectedAttach: false, + }, + { + desc: "Route namespace matches the Gateway namespace", + gateway: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway", + Namespace: "default", + }, + }, + listener: v1alpha2.Listener{ + Name: "foo", + }, + routeNamespace: "default", + routeSpec: v1alpha2.CommonRouteSpec{ + ParentRefs: []v1alpha2.ParentRef{ + { + SectionName: sectionNamePtr("foo"), + Name: "gateway", + Kind: kindPtr("Gateway"), + Group: groupPtr(v1alpha2.GroupName), + }, + }, + }, + expectedAttach: true, + }, + { + desc: "Namespace matches the Gateway namespace", + gateway: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway", + Namespace: "default", + }, + }, + listener: v1alpha2.Listener{ + Name: "foo", + }, + routeNamespace: "bar", + routeSpec: v1alpha2.CommonRouteSpec{ + ParentRefs: []v1alpha2.ParentRef{ + { + SectionName: sectionNamePtr("foo"), + Name: "gateway", + Namespace: namespacePtr("default"), + Kind: kindPtr("Gateway"), + Group: groupPtr(v1alpha2.GroupName), + }, + }, + }, + expectedAttach: true, + }, + { + desc: "Only one ParentRef matches the Gateway", + gateway: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway", + Namespace: "default", + }, + }, + listener: v1alpha2.Listener{ + Name: "foo", + }, + routeNamespace: "bar", + routeSpec: v1alpha2.CommonRouteSpec{ + ParentRefs: []v1alpha2.ParentRef{ + { + Name: "gateway2", + Namespace: namespacePtr("default"), + Kind: kindPtr("Gateway"), + Group: groupPtr(v1alpha2.GroupName), + }, + { + Name: "gateway", + Namespace: namespacePtr("default"), + Kind: kindPtr("Gateway"), + Group: groupPtr(v1alpha2.GroupName), + }, + }, + }, + expectedAttach: true, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + got := shouldAttach(test.gateway, test.listener, test.routeNamespace, test.routeSpec) + assert.Equal(t, test.expectedAttach, got) + }) + } +} + +func Test_matchingHostnames(t *testing.T) { + tests := []struct { + desc string + listener v1alpha2.Listener + hostnames []v1alpha2.Hostname + want []v1alpha2.Hostname + }{ + { + desc: "Empty", + }, + { + desc: "Only listener hostname", + listener: v1alpha2.Listener{ + Hostname: hostnamePtr("foo.com"), + }, + want: []v1alpha2.Hostname{"foo.com"}, + }, + { + desc: "Only Route hostname", + hostnames: []v1alpha2.Hostname{"foo.com"}, + want: []v1alpha2.Hostname{"foo.com"}, + }, + { + desc: "Matching hostname", + listener: v1alpha2.Listener{ + Hostname: hostnamePtr("foo.com"), + }, + hostnames: []v1alpha2.Hostname{"foo.com"}, + want: []v1alpha2.Hostname{"foo.com"}, + }, + { + desc: "Matching hostname with wildcard", + listener: v1alpha2.Listener{ + Hostname: hostnamePtr("*.foo.com"), + }, + hostnames: []v1alpha2.Hostname{"*.foo.com"}, + want: []v1alpha2.Hostname{"*.foo.com"}, + }, + { + desc: "Matching subdomain with listener wildcard", + listener: v1alpha2.Listener{ + Hostname: hostnamePtr("*.foo.com"), + }, + hostnames: []v1alpha2.Hostname{"bar.foo.com"}, + want: []v1alpha2.Hostname{"bar.foo.com"}, + }, + { + desc: "Matching subdomain with route hostname wildcard", + listener: v1alpha2.Listener{ + Hostname: hostnamePtr("bar.foo.com"), + }, + hostnames: []v1alpha2.Hostname{"*.foo.com"}, + want: []v1alpha2.Hostname{"bar.foo.com"}, + }, + { + desc: "Non matching root domain with listener wildcard", + listener: v1alpha2.Listener{ + Hostname: hostnamePtr("*.foo.com"), + }, + hostnames: []v1alpha2.Hostname{"foo.com"}, + }, + { + desc: "Non matching root domain with route hostname wildcard", + listener: v1alpha2.Listener{ + Hostname: hostnamePtr("foo.com"), + }, + hostnames: []v1alpha2.Hostname{"*.foo.com"}, + }, + { + desc: "Multiple route hostnames with one matching route hostname", + listener: v1alpha2.Listener{ + Hostname: hostnamePtr("*.foo.com"), + }, + hostnames: []v1alpha2.Hostname{"bar.com", "test.foo.com", "test.buz.com"}, + want: []v1alpha2.Hostname{"test.foo.com"}, + }, + { + desc: "Multiple route hostnames with non matching route hostname", + listener: v1alpha2.Listener{ + Hostname: hostnamePtr("*.fuz.com"), + }, + hostnames: []v1alpha2.Hostname{"bar.com", "test.foo.com", "test.buz.com"}, + }, + { + desc: "Multiple route hostnames with multiple matching route hostnames", + listener: v1alpha2.Listener{ + Hostname: hostnamePtr("*.foo.com"), + }, + hostnames: []v1alpha2.Hostname{"toto.foo.com", "test.foo.com", "test.buz.com"}, + want: []v1alpha2.Hostname{"toto.foo.com", "test.foo.com"}, + }, + } + + for _, test := range tests { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + got := matchingHostnames(test.listener, test.hostnames) + assert.Equal(t, test.want, got) + }) + } +} + +func Test_getAllowedRoutes(t *testing.T) { + tests := []struct { + desc string + listener v1alpha2.Listener + supportedRouteKinds []v1alpha2.RouteGroupKind + wantKinds []v1alpha2.RouteGroupKind + wantErr bool + }{ + { + desc: "Empty", + }, + { + desc: "Empty AllowedRoutes", + supportedRouteKinds: []v1alpha2.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(v1alpha2.GroupName)}, + }, + wantKinds: []v1alpha2.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(v1alpha2.GroupName)}, + }, + }, + { + desc: "AllowedRoutes with unsupported Group", + listener: v1alpha2.Listener{ + AllowedRoutes: &v1alpha2.AllowedRoutes{ + Kinds: []v1alpha2.RouteGroupKind{{ + Kind: kindTLSRoute, Group: groupPtr("foo"), + }}, + }, + }, + supportedRouteKinds: []v1alpha2.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(v1alpha2.GroupName)}, + }, + wantErr: true, + }, + { + desc: "AllowedRoutes with nil Group", + listener: v1alpha2.Listener{ + AllowedRoutes: &v1alpha2.AllowedRoutes{ + Kinds: []v1alpha2.RouteGroupKind{{ + Kind: kindTLSRoute, Group: nil, + }}, + }, + }, + supportedRouteKinds: []v1alpha2.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(v1alpha2.GroupName)}, + }, + wantErr: true, + }, + { + desc: "AllowedRoutes with unsupported Kind", + listener: v1alpha2.Listener{ + AllowedRoutes: &v1alpha2.AllowedRoutes{ + Kinds: []v1alpha2.RouteGroupKind{{ + Kind: "foo", Group: groupPtr(v1alpha2.GroupName), + }}, + }, + }, + supportedRouteKinds: []v1alpha2.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(v1alpha2.GroupName)}, + }, + wantErr: true, + }, + { + desc: "Supported AllowedRoutes", + listener: v1alpha2.Listener{ + AllowedRoutes: &v1alpha2.AllowedRoutes{ + Kinds: []v1alpha2.RouteGroupKind{{ + Kind: kindTLSRoute, Group: groupPtr(v1alpha2.GroupName), + }}, + }, + }, + supportedRouteKinds: []v1alpha2.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(v1alpha2.GroupName)}, + }, + wantKinds: []v1alpha2.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(v1alpha2.GroupName)}, + }, + }, + { + desc: "Supported AllowedRoutes with duplicates", + listener: v1alpha2.Listener{ + AllowedRoutes: &v1alpha2.AllowedRoutes{ + Kinds: []v1alpha2.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(v1alpha2.GroupName)}, + {Kind: kindTCPRoute, Group: groupPtr(v1alpha2.GroupName)}, + {Kind: kindTLSRoute, Group: groupPtr(v1alpha2.GroupName)}, + {Kind: kindTCPRoute, Group: groupPtr(v1alpha2.GroupName)}, + }, + }, + }, + supportedRouteKinds: []v1alpha2.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(v1alpha2.GroupName)}, + {Kind: kindTCPRoute, Group: groupPtr(v1alpha2.GroupName)}, + }, + wantKinds: []v1alpha2.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(v1alpha2.GroupName)}, + {Kind: kindTCPRoute, Group: groupPtr(v1alpha2.GroupName)}, + }, + }, + } + + for _, test := range tests { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + got, conditions := getAllowedRouteKinds(test.listener, test.supportedRouteKinds) + if test.wantErr { + require.NotEmpty(t, conditions, "no conditions") + return + } + + require.Len(t, conditions, 0) + assert.Equal(t, test.wantKinds, got) + }) + } +} + +func hostnamePtr(hostname v1alpha2.Hostname) *v1alpha2.Hostname { + return &hostname +} + +func groupPtr(group v1alpha2.Group) *v1alpha2.Group { + return &group +} + +func sectionNamePtr(sectionName v1alpha2.SectionName) *v1alpha2.SectionName { + return §ionName +} + +func namespacePtr(namespace v1alpha2.Namespace) *v1alpha2.Namespace { + return &namespace +} + +func kindPtr(kind v1alpha2.Kind) *v1alpha2.Kind { + return &kind +} + +func pathMatchTypePtr(p v1alpha2.PathMatchType) *v1alpha2.PathMatchType { return &p } + +func headerMatchTypePtr(h v1alpha2.HeaderMatchType) *v1alpha2.HeaderMatchType { return &h }