diff --git a/apis/v1alpha2/gateway_types.go b/apis/v1alpha2/gateway_types.go index 9c424d2c03..5f5342094a 100644 --- a/apis/v1alpha2/gateway_types.go +++ b/apis/v1alpha2/gateway_types.go @@ -41,7 +41,7 @@ type Gateway struct { // Status defines the current state of Gateway. // - // +kubebuilder:default={conditions: {{type: "Scheduled", status: "False", reason:"NotReconciled", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + // +kubebuilder:default={conditions: {{type: "Scheduled", status: "Unknown", reason:"NotReconciled", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}} Status GatewayStatus `json:"status,omitempty"` } @@ -72,6 +72,9 @@ type GatewaySpec struct { // logical endpoints that are bound on this Gateway's addresses. // At least one Listener MUST be specified. // + // Each listener in a Gateway must have a unique combination of Hostname, + // Port, and Protocol. + // // 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 @@ -142,10 +145,8 @@ type GatewaySpec struct { Addresses []GatewayAddress `json:"addresses,omitempty"` } -// 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. +// Listener embodies the concept of a logical endpoint where a Gateway accepts +// network connections. type Listener struct { // Name is the name of the Listener. // @@ -157,10 +158,20 @@ type Listener struct { // field is ignored for protocols that don't require hostname based // matching. // + // Implementations MUST apply Hostname matching appropriately for each of + // the following protocols: + // + // * 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. + // // 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 - // admitted. For more information, refer to the Route specific 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. // // Support: Core @@ -175,18 +186,6 @@ type Listener struct { Port PortNumber `json:"port"` // Protocol specifies the network protocol this listener expects to receive. - // The GatewayClass MUST apply the Hostname match appropriately for each - // protocol: - // - // * 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. // // Support: Core Protocol ProtocolType `json:"protocol"` @@ -426,8 +425,6 @@ type RouteGroupKind struct { type GatewayAddress struct { // Type of the address. // - // Support: Extended - // // +optional // +kubebuilder:default=IPAddress Type *AddressType `json:"type,omitempty"` @@ -503,7 +500,7 @@ type GatewayStatus struct { // +listType=map // +listMapKey=type // +kubebuilder:validation:MaxItems=8 - // +kubebuilder:default={{type: "Scheduled", status: "False", reason:"NotReconciled", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}} + // +kubebuilder:default={{type: "Scheduled", status: "Unknown", reason:"NotReconciled", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}} Conditions []metav1.Condition `json:"conditions,omitempty"` // Listeners provide status for each unique listener port defined in the Spec. @@ -596,12 +593,11 @@ const ( // more Listeners are not ready to serve traffic. GatewayReasonListenersNotReady GatewayConditionReason = "ListenersNotReady" - // This reason is used with the "Ready" condition when the requested - // address has not been assigned to the Gateway. This reason - // can be used to express a range of circumstances, including - // (but not limited to) IPAM address exhaustion, invalid - // or unsupported address requests, or a named address not - // being found. + // This reason is used with the "Ready" condition when none of the requested + // addresses have been assigned to the Gateway. This reason can be used to + // express a range of circumstances, including (but not limited to) IPAM + // address exhaustion, invalid or unsupported address requests, or a named + // address not being found. GatewayReasonAddressNotAssigned GatewayConditionReason = "AddressNotAssigned" ) @@ -611,17 +607,14 @@ type ListenerStatus struct { Name SectionName `json:"name"` // SupportedKinds is the list indicating the Kinds supported by this - // listener. When this is not specified on the Listener, this MUST represent - // the kinds an implementation supports for the specified protocol. When - // there are kinds specified on the Listener, this MUST represent the - // intersection of those kinds and the kinds supported by the implementation - // for the specified protocol. - // - // If kinds are specified in Spec that are not supported, an implementation - // MUST set the "ResolvedRefs" condition to "False" with the - // "InvalidRouteKinds" reason. If both valid and invalid Route kinds are - // specified, the implementation should support the valid Route kinds that - // have been specified. + // listener. This MUST represent the kinds an implementation supports for + // that Listener configuration. + // + // 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. // // +kubebuilder:validation:MaxItems=8 SupportedKinds []RouteGroupKind `json:"supportedKinds"` @@ -718,8 +711,11 @@ const ( // interoperability. ListenerConditionDetached ListenerConditionType = "Detached" - // This reason is used with the "Detached" condition when the - // Listener requests a port that cannot be used on the Gateway. + // This reason is used with the "Detached" condition when the Listener + // requests a port that cannot be used on the Gateway. This reason could be + // used in a number of instances, including: + // * The port is already in use. + // * The port is not supported by the implementation. ListenerReasonPortUnavailable ListenerConditionReason = "PortUnavailable" // This reason is used with the "Detached" condition when the @@ -733,9 +729,11 @@ const ( // protocol type is not supported. ListenerReasonUnsupportedProtocol ListenerConditionReason = "UnsupportedProtocol" - // This reason is used with the "Detached" condition when - // the Listener could not be attached to the Gateway because the - // requested address is not supported. + // This reason is used with the "Detached" condition when the Listener could + // not be attached to the Gateway because the requested address is not + // supported. This reason could be used in a number of instances, including: + // * The address is already in use. + // * The type of address is not supported by the implementation. ListenerReasonUnsupportedAddress ListenerConditionReason = "UnsupportedAddress" // This reason is used with the "Detached" condition when the condition is diff --git a/apis/v1alpha2/gatewayclass_types.go b/apis/v1alpha2/gatewayclass_types.go index 8a77e854c1..829de318cc 100644 --- a/apis/v1alpha2/gatewayclass_types.go +++ b/apis/v1alpha2/gatewayclass_types.go @@ -56,7 +56,7 @@ type GatewayClass struct { // Status defines the current state of GatewayClass. // - // +kubebuilder:default={conditions: {{type: "Admitted", status: "False", message: "Waiting for controller", reason: "Waiting", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + // +kubebuilder:default={conditions: {{type: "Accepted", status: "Unknown", message: "Waiting for controller", reason: "Waiting", lastTransitionTime: "1970-01-01T00:00:00Z"}}} Status GatewayClassStatus `json:"status,omitempty"` } @@ -69,19 +69,15 @@ const ( // GatewayClassSpec reflects the configuration of a class of Gateways. type GatewayClassSpec struct { - // Controller is a domain/path string that indicates the - // controller that is managing Gateways of this class. + // 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. // // Example: "example.net/gateway-controller". // // This field is not mutable and cannot be empty. // - // The format of this field is DOMAIN "/" PATH, where DOMAIN is a valid - // Kubernetes name (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names) - // and PATH is a valid HTTP path as defined by RFC 3986. - // // Support: Core - Controller GatewayController `json:"controller"` + ControllerName GatewayController `json:"controllerName"` // ParametersRef is a reference to a resource that contains the configuration // parameters corresponding to the GatewayClass. This is optional if the @@ -130,8 +126,8 @@ type ParametersReference struct { Scope *string `json:"scope,omitempty"` // 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". + // This field is required when scope is set to "Namespace" and must be unset + // when scope is set to "Cluster". // // +optional Namespace *Namespace `json:"namespace,omitempty"` @@ -147,19 +143,19 @@ type GatewayClassConditionType string type GatewayClassConditionReason string const ( - // This condition indicates whether the GatewayClass has been admitted by + // This condition indicates whether the GatewayClass has been accepted by // the controller requested in the `spec.controller` field. // - // This condition defaults to False, and MUST be set by a controller when it - // sees a GatewayClass using its controller string. The status of this - // condition MUST be set to true if the controller will support provisioning + // This condition defaults to Unknown, and MUST be set by a controller when + // it sees a GatewayClass using its controller string. The status of this + // condition MUST be set to True if the controller will support provisioning // Gateways using this class. Otherwise, this status MUST be set to False. // If the status is set to False, the controller SHOULD set a Message and // Reason as an explanation. // // Possible reasons for this condition to be true are: // - // * "Admitted" + // * "Accepted" // // Possible reasons for this condition to be False are: // @@ -168,18 +164,18 @@ const ( // // Controllers should prefer to use the values of GatewayClassConditionReason // for the corresponding Reason, where appropriate. - GatewayClassConditionStatusAdmitted GatewayClassConditionType = "Admitted" + GatewayClassConditionStatusAccepted GatewayClassConditionType = "Accepted" - // This reason is used with the "Admitted" condition when the condition is + // This reason is used with the "Accepted" condition when the condition is // true. - GatewayClassReasonAdmitted GatewayClassConditionReason = "Admitted" + GatewayClassReasonAccepted GatewayClassConditionReason = "Accepted" - // This reason is used with the "Admitted" condition when the - // GatewayClass was not admitted because the parametersRef field + // This reason is used with the "Accepted" condition when the + // GatewayClass was not accepted because the parametersRef field // was invalid, with more detail in the message. GatewayClassReasonInvalidParameters GatewayClassConditionReason = "InvalidParameters" - // This reason is used with the "Admitted" condition when the + // This reason is used with the "Accepted" condition when the // requested controller has not yet made a decision about whether // to admit the GatewayClass. It is the default Reason on a new // GatewayClass. @@ -198,7 +194,7 @@ type GatewayClassStatus struct { // +listType=map // +listMapKey=type // +kubebuilder:validation:MaxItems=8 - // +kubebuilder:default={{type: "Admitted", status: "False", message: "Waiting for controller", reason: "Waiting", lastTransitionTime: "1970-01-01T00:00:00Z"}} + // +kubebuilder:default={{type: "Accepted", status: "Unknown", message: "Waiting for controller", reason: "Waiting", lastTransitionTime: "1970-01-01T00:00:00Z"}} Conditions []metav1.Condition `json:"conditions,omitempty"` } diff --git a/apis/v1alpha2/httproute_types.go b/apis/v1alpha2/httproute_types.go index 4e0e9f368b..87ade87577 100644 --- a/apis/v1alpha2/httproute_types.go +++ b/apis/v1alpha2/httproute_types.go @@ -28,7 +28,10 @@ import ( // +kubebuilder:printcolumn:name="Hostnames",type=string,JSONPath=`.spec.hostnames` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` -// HTTPRoute is the Schema for the HTTPRoute resource. +// 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. type HTTPRoute struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -53,14 +56,13 @@ type HTTPRouteList struct { type HTTPRouteSpec struct { CommonRouteSpec `json:",inline"` - // 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: + // 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: // // 1. IPs are not allowed. - // 2. The `:` delimiter is not respected because ports are not allowed. + // 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + // label must appear by itself as the first label. // // If a hostname is specified by both the Listener and HTTPRoute, there // must be at least one intersecting hostname for the HTTPRoute to be @@ -69,12 +71,11 @@ type HTTPRouteSpec struct { // * 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 as the hostname matches HTTPRoutes + // * 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, `a.b.example.com`, `example.com`, and `test.example.net` would - // not match. + // hand, `example.com` and `test.example.net` would not match. // // If both the Listener and HTTPRoute have specified hostnames, any // HTTPRoute hostnames that do not match the Listener hostname MUST be @@ -83,7 +84,7 @@ type HTTPRouteSpec struct { // `test.example.net` must not be considered for a match. // // If hostnames do not match with the criteria above, then the HTTPRoute is - // not admitted, and the implementation must raise an 'Admitted' Condition + // not accepted, and the implementation must raise an 'Accepted' Condition // with a status of `False` for the target Listener(s). // // Support: Core @@ -101,8 +102,8 @@ type HTTPRouteSpec struct { } // HTTPRouteRule defines semantics for matching an HTTP request based on -// conditions, optionally executing additional processing steps, and forwarding -// the request to an API object. +// conditions (matches), processing it (filters), and forwarding the request to +// an API object (backendRefs). type HTTPRouteRule struct { // Matches define conditions used for matching the rule against incoming // HTTP requests. Each match is independent, i.e. this rule will be matched @@ -134,26 +135,22 @@ type HTTPRouteRule struct { // path match on "/", which has the effect of matching every // HTTP request. // + // Proxy or Load Balancer routing configuration generated from HTTPRoutes + // MUST prioritize rules based on the following criteria, continuing on + // ties: // - // 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: - // - // * The longest matching hostname. - // * The longest matching non-wildcard hostname. - // * The longest matching path. + // * The longest hostname. + // * The longest non-wildcard hostname. + // * The longest path. // * The largest number of header matches. // * The largest number of query param matches. // // If ties still exist across multiple Routes, matching precedence MUST be // determined in order of the following criteria, continuing on ties: // - // * 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 oldest Route based on creation timestamp. // * The Route appearing first in alphabetical order by - // "/". For example, foo/bar is given precedence over - // foo/baz. + // "/". // // If ties still exist within the Route that has been given precedence, // matching precedence MUST be granted to the first matching rule meeting @@ -177,7 +174,8 @@ type HTTPRouteRule struct { // - Implementation-specific custom filters have no API guarantees across // implementations. // - // Specifying a core filter multiple times has unspecified or custom conformance. + // Specifying a core filter multiple times has unspecified or custom + // conformance. // // Support: Core // @@ -455,16 +453,15 @@ type HTTPRouteMatch struct { Method *HTTPMethod `json:"method,omitempty"` } -// 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 -// +union +// 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. +// 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 +union type HTTPRouteFilter struct { // Type identifies the type of filter to apply. As with other API fields, // types are classified into three conformance levels: @@ -487,6 +484,10 @@ type HTTPRouteFilter struct { // Implementers are encouraged to define custom implementation types to // extend the core API with implementation-specific behavior. // + // If a reference to a custom filter type cannot be resolved, the filter + // MUST NOT be skipped. Instead, requests that would have been processed by + // that filter MUST receive a HTTP error response. + // // +unionDiscriminator Type HTTPRouteFilterType `json:"type"` @@ -499,6 +500,8 @@ type HTTPRouteFilter struct { RequestHeaderModifier *HTTPRequestHeaderFilter `json:"requestHeaderModifier,omitempty"` // RequestMirror defines a schema for a filter that mirrors requests. + // Requests are sent to the specified destination, but responses from + // that destination are ignored. // // Support: Extended // diff --git a/apis/v1alpha2/referencepolicy_types.go b/apis/v1alpha2/referencepolicy_types.go index 6bfc62eb1b..149ae89b65 100644 --- a/apis/v1alpha2/referencepolicy_types.go +++ b/apis/v1alpha2/referencepolicy_types.go @@ -86,7 +86,7 @@ type ReferencePolicySpec struct { // ReferencePolicyFrom describes trusted namespaces and kinds. type ReferencePolicyFrom struct { // Group is the group of the referent. - // When empty, the "core" API group is inferred. + // When empty, the Kubernetes core API group is inferred. // // Support: Core Group Group `json:"group"` @@ -111,7 +111,7 @@ type ReferencePolicyFrom struct { // references. type ReferencePolicyTo struct { // Group is the group of the referent. - // When empty, the "core" API group is inferred. + // When empty, the Kubernetes core API group is inferred. // // Support: Core Group Group `json:"group"` diff --git a/apis/v1alpha2/shared_types.go b/apis/v1alpha2/shared_types.go index 8710768eea..4b11c39b56 100644 --- a/apis/v1alpha2/shared_types.go +++ b/apis/v1alpha2/shared_types.go @@ -166,9 +166,9 @@ type BackendRef struct { type RouteConditionType string const ( - // This condition indicates whether the route has been admitted or rejected + // This condition indicates whether the route has been accepted or rejected // by a Gateway, and why. - ConditionRouteAdmitted RouteConditionType = "Admitted" + ConditionRouteAccepted RouteConditionType = "Accepted" // This condition indicates whether the controller was able to resolve all // the object references for the Route. @@ -182,16 +182,16 @@ type RouteParentStatus struct { // RouteParentStatus struct describes the status of. ParentRef ParentRef `json:"parentRef"` - // Controller is a domain/path string that indicates the controller that - // wrote this status. This corresponds with the controller field on - // GatewayClass. + // 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. // // Example: "example.net/gateway-controller". // // 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). - Controller GatewayController `json:"controller"` + ControllerName GatewayController `json:"controllerName"` // 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 @@ -199,14 +199,14 @@ type RouteParentStatus struct { // // 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 "Admitted" condition on the - // Route, to indicate whether the route has been admitted or rejected by the + // 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. // - // A Route MUST be considered "Admitted" if at least one of the Route's + // A Route MUST be considered "Accepted" if at least one of the Route's // rules is implemented by the Gateway. // - // There are a number of cases where the "Admitted" condition may not be set + // There are a number of cases where the "Accepted" condition may not be set // due to lack of controller visibility, that includes when: // // * The Route refers to a non-existent parent. @@ -230,6 +230,11 @@ type RouteStatus struct { // first sees the route and should update the entry as appropriate when the // route or gateway is modified. // + // 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. + // // A maximum of 32 Gateways will be represented in this list. An empty list // means the route has not been attached to any Gateway. // @@ -237,12 +242,12 @@ type RouteStatus struct { Parents []RouteParentStatus `json:"parents"` } -// 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: +// Hostname is the fully qualified domain name of a network host. This matches +// the RFC 1123 definition of a hostname with 2 notable exceptions: // -// 1. IP literals are not allowed. -// 2. The `:` delimiter is not respected because ports are not allowed. +// 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. // // 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 @@ -314,8 +319,7 @@ type Kind string // +kubebuilder:validation:MaxLength=63 type Namespace string -// SectionName is the name of a section in a Kubernetes resource. It must be a -// RFC 1123 subdomain. +// SectionName is the name of a section in a Kubernetes resource. // // This validation is based off of the corresponding Kubernetes validation: // https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 diff --git a/apis/v1alpha2/tcproute_types.go b/apis/v1alpha2/tcproute_types.go index d588f83713..60d805787d 100644 --- a/apis/v1alpha2/tcproute_types.go +++ b/apis/v1alpha2/tcproute_types.go @@ -27,7 +27,9 @@ import ( // +kubebuilder:storageversion // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` -// TCPRoute is the Schema for the TCPRoute resource. +// 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. type TCPRoute struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/apis/v1alpha2/tlsroute_types.go b/apis/v1alpha2/tlsroute_types.go index 25a431c304..bdab4d58a7 100644 --- a/apis/v1alpha2/tlsroute_types.go +++ b/apis/v1alpha2/tlsroute_types.go @@ -49,26 +49,35 @@ type TLSRouteSpec struct { CommonRouteSpec `json:",inline"` // Hostnames defines a set of SNI names that should match against the - // SNI attribute of TLS ClientHello message in TLS handshake. + // SNI attribute of TLS ClientHello message in TLS handshake. This matches + // the RFC 1123 definition of a hostname with 2 notable exceptions: // - // 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 == `*`). + // 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. // - // Requests will be matched against the SNI attribute in the following - // order: + // 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: // - // 1. If SNI is precise, the request matches this Route if the SNI in - // ClientHello is equal to one of the defined SNIs. - // 2. If SNI is a wildcard, then the request matches this Route if the - // SNI is to equal to the suffix (removing the first label) of the - // wildcard. - // 3. If SNIs are unspecified, all requests associated with the gateway TLS - // listener will match. This can be used to define a default backend - // for a TLS listener. + // * 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. + // + // 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. + // + // If all hostnames do not match with the criteria above, then the TLSRoute + // is not accepted, and the implementation must raise an 'Accepted' + // Condition with a status of `False` for the target Listener(s). // // Support: Core // diff --git a/apis/v1alpha2/udproute_types.go b/apis/v1alpha2/udproute_types.go index 676f033d0c..361713afb2 100644 --- a/apis/v1alpha2/udproute_types.go +++ b/apis/v1alpha2/udproute_types.go @@ -27,7 +27,9 @@ import ( // +kubebuilder:storageversion // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` -// UDPRoute is a resource that specifies how a Gateway should forward UDP traffic. +// UDPRoute provides a way to route UDP traffic. When combined with a Gateway +// listener, it can be used to forward traffic on the port specified by the +// listener to a set of backends specified by the UDPRoute. type UDPRoute struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/apis/v1alpha2/validation/gatewayclass.go b/apis/v1alpha2/validation/gatewayclass.go index 5f496da0cc..19667aaac2 100644 --- a/apis/v1alpha2/validation/gatewayclass.go +++ b/apis/v1alpha2/validation/gatewayclass.go @@ -30,8 +30,8 @@ func ValidateGatewayClassUpdate(oldClass, newClass *gatewayv1a2.GatewayClass) fi return nil } var errs field.ErrorList - if oldClass.Spec.Controller != newClass.Spec.Controller { - errs = append(errs, field.Invalid(field.NewPath("spec.controller"), newClass.Spec.Controller, + if oldClass.Spec.ControllerName != newClass.Spec.ControllerName { + errs = append(errs, field.Invalid(field.NewPath("spec.controllerName"), newClass.Spec.ControllerName, "cannot update an immutable field")) } return errs diff --git a/apis/v1alpha2/validation/gatewayclass_test.go b/apis/v1alpha2/validation/gatewayclass_test.go index 323ca6a71c..0518ddb1f9 100644 --- a/apis/v1alpha2/validation/gatewayclass_test.go +++ b/apis/v1alpha2/validation/gatewayclass_test.go @@ -40,12 +40,12 @@ func TestValidateGatewayClassUpdate(t *testing.T) { args: args{ oldClass: &gatewayv1a2.GatewayClass{ Spec: gatewayv1a2.GatewayClassSpec{ - Controller: "foo", + ControllerName: "foo", }, }, newClass: &gatewayv1a2.GatewayClass{ Spec: gatewayv1a2.GatewayClassSpec{ - Controller: "foo", + ControllerName: "foo", ParametersRef: &gatewayv1a2.ParametersReference{ Group: "example.com", Kind: "GatewayClassConfig", @@ -61,19 +61,19 @@ func TestValidateGatewayClassUpdate(t *testing.T) { args: args{ oldClass: &gatewayv1a2.GatewayClass{ Spec: gatewayv1a2.GatewayClassSpec{ - Controller: "example.com/gateway", + ControllerName: "example.com/gateway", }, }, newClass: &gatewayv1a2.GatewayClass{ Spec: gatewayv1a2.GatewayClassSpec{ - Controller: "example.org/gateway", + ControllerName: "example.org/gateway", }, }, }, want: field.ErrorList{ { Type: field.ErrorTypeInvalid, - Field: "spec.controller", + Field: "spec.controllerName", Detail: "cannot update an immutable field", BadValue: gatewayv1a2.GatewayController("example.org/gateway"), }, diff --git a/config/crd/v1alpha2/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/v1alpha2/gateway.networking.k8s.io_gatewayclasses.yaml index 9b88b20331..19055417ae 100644 --- a/config/crd/v1alpha2/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/v1alpha2/gateway.networking.k8s.io_gatewayclasses.yaml @@ -63,14 +63,11 @@ 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: - \"example.net/gateway-controller\". \n This field is not mutable - and cannot be empty. \n The format of this field is DOMAIN \"/\" - PATH, where DOMAIN is a valid Kubernetes name (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names) - and PATH is a valid HTTP path as defined by RFC 3986. \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\/\-._~%!$&'()*+,;=:]+$ @@ -107,8 +104,8 @@ 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". + field is required when scope is set to "Namespace" and must + be unset when scope is set to "Cluster". maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ @@ -127,7 +124,7 @@ spec: - name type: object required: - - controller + - controllerName type: object status: default: @@ -135,8 +132,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: @@ -144,8 +141,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." diff --git a/config/crd/v1alpha2/gateway.networking.k8s.io_gateways.yaml b/config/crd/v1alpha2/gateway.networking.k8s.io_gateways.yaml index 9197011bc1..c95cfec3ef 100644 --- a/config/crd/v1alpha2/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/v1alpha2/gateway.networking.k8s.io_gateways.yaml @@ -77,7 +77,7 @@ spec: properties: type: default: IPAddress - description: "Type of the address. \n Support: Extended" + description: Type of the address. enum: - IPAddress - Hostname @@ -104,33 +104,32 @@ 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: allowedRoutes: default: @@ -268,11 +267,19 @@ spec: 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 For HTTPRoute - and TLSRoute resources, there is an interaction with the `spec.hostnames` + 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 admitted. For more information, refer to the Route specific + 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 @@ -295,15 +302,7 @@ spec: 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" + expects to receive. \n Support: Core" type: string tls: description: "TLS is the TLS configuration for the Listener. @@ -418,7 +417,7 @@ 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: @@ -433,7 +432,7 @@ spec: properties: type: default: IPAddress - description: "Type of the address. \n Support: Extended" + description: Type of the address. enum: - IPAddress - Hostname @@ -456,7 +455,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 @@ -635,16 +634,14 @@ spec: type: string supportedKinds: description: "SupportedKinds is the list indicating the Kinds - supported by this listener. When this is not specified on - the Listener, this MUST represent the kinds an implementation - supports for the specified protocol. When there are kinds - specified on the Listener, this MUST represent the intersection - of those kinds and the kinds supported by the implementation - for the specified protocol. \n If kinds are specified in Spec - that are not supported, an implementation MUST set the \"ResolvedRefs\" - condition to \"False\" with the \"InvalidRouteKinds\" reason. - If both valid and invalid Route kinds are specified, the implementation - should support the valid Route kinds that have been specified." + 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. diff --git a/config/crd/v1alpha2/gateway.networking.k8s.io_httproutes.yaml b/config/crd/v1alpha2/gateway.networking.k8s.io_httproutes.yaml index 1a7f302dfa..5b6a039b76 100644 --- a/config/crd/v1alpha2/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/v1alpha2/gateway.networking.k8s.io_httproutes.yaml @@ -28,7 +28,10 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: HTTPRoute is the Schema for the HTTPRoute resource. + 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 @@ -48,42 +51,41 @@ spec: 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 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 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, `a.b.example.com`, `example.com`, and `test.example.net` - would not match. \n If both the Listener and HTTPRoute have specified + 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 hostnames do not match with the criteria above, then the HTTPRoute is not - admitted, and the implementation must raise an 'Admitted' Condition + accepted, and the implementation must raise an 'Accepted' Condition with a status of `False` for the target Listener(s). \n Support: Core" items: description: "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`). \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." + 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])?)*$ @@ -188,8 +190,8 @@ spec: 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. + 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 @@ -212,18 +214,18 @@ spec: 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' + 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. 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 + +union' properties: extensionRef: description: "ExtensionRef is an optional, implementation-specific @@ -367,7 +369,9 @@ spec: type: object requestMirror: description: "RequestMirror defines a schema for - a filter that mirrors requests. \n Support: Extended" + 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 @@ -505,7 +509,11 @@ spec: 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." + 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 @@ -597,16 +605,17 @@ spec: 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' + 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. 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 + +union' properties: extensionRef: description: "ExtensionRef is an optional, implementation-specific @@ -742,7 +751,9 @@ spec: type: object requestMirror: description: "RequestMirror defines a schema for a filter - that mirrors requests. \n Support: Extended" + 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 @@ -873,7 +884,10 @@ spec: 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." + 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 @@ -903,24 +917,19 @@ spec: 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 non-wildcard hostname. * The longest - matching path. * The largest number of header matches. * The - largest number of 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. 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." + every HTTP request. \n Proxy or Load Balancer routing configuration + generated from HTTPRoutes MUST prioritize rules based on the + following criteria, continuing on ties: \n * The longest hostname. + * The longest non-wildcard hostname. * The longest path. * + The largest number of header matches. * The largest number + of 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 @@ -1098,8 +1107,12 @@ spec: 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 A maximum of 32 Gateways will be represented in this list. An - empty list means the route has not been attached to any Gateway." + \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. @@ -1111,11 +1124,11 @@ spec: 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 \"Admitted\" condition on the Route, - to indicate whether the route has been admitted or rejected - by the Gateway, and why. \n A Route MUST be considered \"Admitted\" + 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 \"Admitted\" + 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 @@ -1198,12 +1211,13 @@ spec: x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map - controller: - description: "Controller is a domain/path string that indicates - the controller that wrote this status. This corresponds with - the controller 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)." + 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\/\-._~%!$&'()*+,;=:]+$ @@ -1278,7 +1292,7 @@ spec: - name type: object required: - - controller + - controllerName - parentRef type: object maxItems: 32 diff --git a/config/crd/v1alpha2/gateway.networking.k8s.io_referencepolicies.yaml b/config/crd/v1alpha2/gateway.networking.k8s.io_referencepolicies.yaml index 664f6a7678..5ddd515fca 100644 --- a/config/crd/v1alpha2/gateway.networking.k8s.io_referencepolicies.yaml +++ b/config/crd/v1alpha2/gateway.networking.k8s.io_referencepolicies.yaml @@ -63,7 +63,7 @@ spec: properties: group: description: "Group is the group of the referent. When empty, - the \"core\" API group is inferred. \n Support: Core" + the Kubernetes core API group is inferred. \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 @@ -102,7 +102,7 @@ spec: properties: group: description: "Group is the group of the referent. When empty, - the \"core\" API group is inferred. \n Support: Core" + the Kubernetes core API group is inferred. \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 diff --git a/config/crd/v1alpha2/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/v1alpha2/gateway.networking.k8s.io_tcproutes.yaml index 8f216f768b..effee801ac 100644 --- a/config/crd/v1alpha2/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/v1alpha2/gateway.networking.k8s.io_tcproutes.yaml @@ -25,7 +25,9 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: TCPRoute is the Schema for the TCPRoute resource. + 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 @@ -239,8 +241,12 @@ spec: 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 A maximum of 32 Gateways will be represented in this list. An - empty list means the route has not been attached to any Gateway." + \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. @@ -252,11 +258,11 @@ spec: 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 \"Admitted\" condition on the Route, - to indicate whether the route has been admitted or rejected - by the Gateway, and why. \n A Route MUST be considered \"Admitted\" + 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 \"Admitted\" + 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 @@ -339,12 +345,13 @@ spec: x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map - controller: - description: "Controller is a domain/path string that indicates - the controller that wrote this status. This corresponds with - the controller 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)." + 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\/\-._~%!$&'()*+,;=:]+$ @@ -419,7 +426,7 @@ spec: - name type: object required: - - controller + - controllerName - parentRef type: object maxItems: 32 diff --git a/config/crd/v1alpha2/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/v1alpha2/gateway.networking.k8s.io_tlsroutes.yaml index 6b63642558..026c6721cc 100644 --- a/config/crd/v1alpha2/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/v1alpha2/gateway.networking.k8s.io_tlsroutes.yaml @@ -49,32 +49,41 @@ spec: hostnames: description: "Hostnames 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 SNI attribute in the following order: - \n 1. If SNI is precise, the request matches this Route if the SNI - in ClientHello is equal to one of the defined SNIs. 2. If SNI - is a wildcard, then the request matches this Route if the SNI - is to equal to the suffix (removing the first label) of the wildcard. - 3. If SNIs are 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" + 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 all + hostnames do not match with the criteria above, then the TLSRoute + is not accepted, and the implementation must raise an 'Accepted' + Condition with a status of `False` for the target Listener(s). \n + Support: Core" items: description: "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`). \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." + 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])?)*$ @@ -281,8 +290,12 @@ spec: 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 A maximum of 32 Gateways will be represented in this list. An - empty list means the route has not been attached to any Gateway." + \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. @@ -294,11 +307,11 @@ spec: 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 \"Admitted\" condition on the Route, - to indicate whether the route has been admitted or rejected - by the Gateway, and why. \n A Route MUST be considered \"Admitted\" + 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 \"Admitted\" + 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 @@ -381,12 +394,13 @@ spec: x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map - controller: - description: "Controller is a domain/path string that indicates - the controller that wrote this status. This corresponds with - the controller 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)." + 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\/\-._~%!$&'()*+,;=:]+$ @@ -461,7 +475,7 @@ spec: - name type: object required: - - controller + - controllerName - parentRef type: object maxItems: 32 diff --git a/config/crd/v1alpha2/gateway.networking.k8s.io_udproutes.yaml b/config/crd/v1alpha2/gateway.networking.k8s.io_udproutes.yaml index 357cf505a0..bc526b2a1c 100644 --- a/config/crd/v1alpha2/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/v1alpha2/gateway.networking.k8s.io_udproutes.yaml @@ -25,8 +25,9 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: UDPRoute is a resource that specifies how a Gateway should forward - UDP traffic. + description: UDPRoute provides a way to route UDP traffic. When combined with + a Gateway listener, it can be used to forward traffic on the port specified + by the listener to a set of backends specified by the UDPRoute. properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -240,8 +241,12 @@ spec: 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 A maximum of 32 Gateways will be represented in this list. An - empty list means the route has not been attached to any Gateway." + \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. @@ -253,11 +258,11 @@ spec: 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 \"Admitted\" condition on the Route, - to indicate whether the route has been admitted or rejected - by the Gateway, and why. \n A Route MUST be considered \"Admitted\" + 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 \"Admitted\" + 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 @@ -340,12 +345,13 @@ spec: x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map - controller: - description: "Controller is a domain/path string that indicates - the controller that wrote this status. This corresponds with - the controller 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)." + 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\/\-._~%!$&'()*+,;=:]+$ @@ -420,7 +426,7 @@ spec: - name type: object required: - - controller + - controllerName - parentRef type: object maxItems: 32 diff --git a/examples/v1alpha2/basic-http.yaml b/examples/v1alpha2/basic-http.yaml index 7efa5eea9d..32913917b0 100644 --- a/examples/v1alpha2/basic-http.yaml +++ b/examples/v1alpha2/basic-http.yaml @@ -3,7 +3,7 @@ kind: GatewayClass metadata: name: acme-lb spec: - controller: acme.io/gateway-controller + controllerName: acme.io/gateway-controller parametersRef: name: acme-lb group: acme.io diff --git a/examples/v1alpha2/default-match-http.yaml b/examples/v1alpha2/default-match-http.yaml index 13b627b7f0..a67d23772a 100644 --- a/examples/v1alpha2/default-match-http.yaml +++ b/examples/v1alpha2/default-match-http.yaml @@ -3,7 +3,7 @@ kind: GatewayClass metadata: name: default-match-example spec: - controller: acme.io/gateway-controller + controllerName: acme.io/gateway-controller --- apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway diff --git a/examples/v1alpha2/http-redirect.yaml b/examples/v1alpha2/http-redirect.yaml index d7d4b528bf..d12e90f8a6 100644 --- a/examples/v1alpha2/http-redirect.yaml +++ b/examples/v1alpha2/http-redirect.yaml @@ -3,7 +3,7 @@ kind: GatewayClass metadata: name: filter-lb spec: - controller: acme.io/gateway-controller + controllerName: acme.io/gateway-controller parametersRef: name: acme-lb group: acme.io diff --git a/hack/invalid-examples/v1alpha2/gatewayclass/invalid-controller.yaml b/hack/invalid-examples/v1alpha2/gatewayclass/invalid-controller.yaml index 3747b2bd56..227c49997b 100644 --- a/hack/invalid-examples/v1alpha2/gatewayclass/invalid-controller.yaml +++ b/hack/invalid-examples/v1alpha2/gatewayclass/invalid-controller.yaml @@ -3,4 +3,4 @@ kind: GatewayClass metadata: name: invalid-controller spec: - controller: example + controllerName: example diff --git a/pkg/admission/server_test.go b/pkg/admission/server_test.go index 4f10114359..659b0829dc 100644 --- a/pkg/admission/server_test.go +++ b/pkg/admission/server_test.go @@ -749,7 +749,7 @@ func TestServeHTTPSubmissions(t *testing.T) { "name": "gateway-class-1" }, "spec": { - "controller": "example.com/foo" + "controllerName": "example.com/foo" } }, "operation": "CREATE" @@ -782,7 +782,7 @@ func TestServeHTTPSubmissions(t *testing.T) { "name": "gateway-class-1" }, "spec": { - "controller": "example.com/foo" + "controllerName": "example.com/foo" } }, "oldObject": { @@ -792,7 +792,7 @@ func TestServeHTTPSubmissions(t *testing.T) { "name": "gateway-class-1" }, "spec": { - "controller": "example.com/foo", + "controllerName": "example.com/foo", "parametersRef": { "name": "foo", "namespace": "bar", @@ -813,7 +813,7 @@ func TestServeHTTPSubmissions(t *testing.T) { }, }, { - name: "update to v1alpha2 GatewayClass controller field" + + name: "update to v1alpha2 GatewayClass controllerName field" + " results in an error ", reqBody: dedent.Dedent(`{ "kind": "AdmissionReview", @@ -832,7 +832,7 @@ func TestServeHTTPSubmissions(t *testing.T) { "name": "gateway-class-1" }, "spec": { - "controller": "example.com/foo" + "controllerName": "example.com/foo" } }, "oldObject": { @@ -842,7 +842,7 @@ func TestServeHTTPSubmissions(t *testing.T) { "name": "gateway-class-1" }, "spec": { - "controller": "example.com/bar" + "controllerName": "example.com/bar" } }, "operation": "UPDATE" @@ -854,7 +854,7 @@ func TestServeHTTPSubmissions(t *testing.T) { Allowed: false, Result: &metav1.Status{ Code: 400, - Message: `spec.controller: Invalid value: "example.com/foo": cannot update an immutable field`, + Message: `spec.controllerName: Invalid value: "example.com/foo": cannot update an immutable field`, }, }, },