diff --git a/apis/v1/doc.go b/apis/v1/doc.go new file mode 100644 index 0000000000..bd223cd9a2 --- /dev/null +++ b/apis/v1/doc.go @@ -0,0 +1,22 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1 contains API Schema definitions for the gateway.networking.k8s.io +// API group. +// +// +kubebuilder:object:generate=true +// +groupName=gateway.networking.k8s.io +package v1 diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go new file mode 100644 index 0000000000..7101a94cb3 --- /dev/null +++ b/apis/v1/gateway_types.go @@ -0,0 +1,1078 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=gateway-api,shortName=gtw +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Class",type=string,JSONPath=`.spec.gatewayClassName` +// +kubebuilder:printcolumn:name="Address",type=string,JSONPath=`.status.addresses[*].value` +// +kubebuilder:printcolumn:name="Programmed",type=string,JSONPath=`.status.conditions[?(@.type=="Programmed")].status` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// Gateway represents an instance of a service-traffic handling infrastructure +// by binding Listeners to a set of IP addresses. +type Gateway struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of Gateway. + Spec GatewaySpec `json:"spec"` + + // Status defines the current state of Gateway. + // + // +kubebuilder:default={conditions: {{type: "Accepted", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type: "Programmed", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + Status GatewayStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// GatewayList contains a list of Gateways. +type GatewayList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Gateway `json:"items"` +} + +// GatewaySpec defines the desired state of Gateway. +// +// Not all possible combinations of options specified in the Spec are +// valid. Some invalid configurations can be caught synchronously via a +// webhook, but there are many cases that will require asynchronous +// signaling via the GatewayStatus block. +type GatewaySpec struct { + // GatewayClassName used for this Gateway. This is the name of a + // GatewayClass resource. + GatewayClassName ObjectName `json:"gatewayClassName"` + + // Listeners associated with this Gateway. Listeners define + // logical endpoints that are bound on this Gateway's addresses. + // At least one Listener MUST be specified. + // + // Each Listener in a set of Listeners (for example, in a single Gateway) + // MUST be _distinct_, in that a traffic flow MUST be able to be assigned to + // exactly one listener. (This section uses "set of Listeners" rather than + // "Listeners in a single Gateway" because implementations MAY merge configuration + // from multiple Gateways onto a single data plane, and these rules _also_ + // apply in that case). + // + // Practically, this means that each listener in a set MUST have a unique + // combination of Port, Protocol, and, if supported by the protocol, Hostname. + // + // Some combinations of port, protocol, and TLS settings are considered + // Core support and MUST be supported by implementations based on their + // targeted conformance profile: + // + // HTTP Profile + // + // 1. HTTPRoute, Port: 80, Protocol: HTTP + // 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: Terminate, TLS keypair provided + // + // TLS Profile + // + // 1. TLSRoute, Port: 443, Protocol: TLS, TLS Mode: Passthrough + // + // "Distinct" Listeners have the following property: + // + // The implementation can match inbound requests to a single distinct + // Listener. When multiple Listeners share values for fields (for + // example, two Listeners with the same Port value), the implementation + // can match requests to only one of the Listeners using other + // Listener fields. + // + // For example, the following Listener scenarios are distinct: + // + // 1. Multiple Listeners with the same Port that all use the "HTTP" + // Protocol that all have unique Hostname values. + // 2. Multiple Listeners with the same Port that use either the "HTTPS" or + // "TLS" Protocol that all have unique Hostname values. + // 3. A mixture of "TCP" and "UDP" Protocol Listeners, where no Listener + // with the same Protocol has the same Port value. + // + // Some fields in the Listener struct have possible values that affect + // whether the Listener is distinct. Hostname is particularly relevant + // for HTTP or HTTPS protocols. + // + // When using the Hostname value to select between same-Port, same-Protocol + // Listeners, the Hostname value must be different on each Listener for the + // Listener to be distinct. + // + // When the Listeners are distinct based on Hostname, inbound request + // hostnames MUST match from the most specific to least specific Hostname + // values to choose the correct Listener and its associated set of Routes. + // + // Exact matches must be processed before wildcard matches, and wildcard + // matches must be processed before fallback (empty Hostname value) + // matches. For example, `"foo.example.com"` takes precedence over + // `"*.example.com"`, and `"*.example.com"` takes precedence over `""`. + // + // Additionally, if there are multiple wildcard entries, more specific + // wildcard entries must be processed before less specific wildcard entries. + // For example, `"*.foo.example.com"` takes precedence over `"*.example.com"`. + // The precise definition here is that the higher the number of dots in the + // hostname to the right of the wildcard character, the higher the precedence. + // + // The wildcard character will match any number of characters _and dots_ to + // the left, however, so `"*.example.com"` will match both + // `"foo.bar.example.com"` _and_ `"bar.example.com"`. + // + // If a set of Listeners contains Listeners that are not distinct, then those + // Listeners are Conflicted, and the implementation MUST set the "Conflicted" + // condition in the Listener Status to "True". + // + // Implementations MAY choose to accept a Gateway with some Conflicted + // Listeners only if they only accept the partial Listener set that contains + // no Conflicted Listeners. To put this another way, implementations may + // accept a partial Listener set only if they throw out *all* the conflicting + // Listeners. No picking one of the conflicting listeners as the winner. + // This also means that the Gateway must have at least one non-conflicting + // Listener in this case, otherwise it violates the requirement that at + // least one Listener must be present. + // + // The implementation MUST set a "ListenersNotValid" condition on the + // Gateway Status when the Gateway contains Conflicted Listeners whether or + // not they accept the Gateway. That Condition SHOULD clearly + // indicate in the Message which Listeners are conflicted, and which are + // Accepted. Additionally, the Listener status for those listeners SHOULD + // indicate which Listeners are conflicted and not Accepted. + // + // A Gateway's Listeners are considered "compatible" if: + // + // 1. They are distinct. + // 2. The implementation can serve them in compliance with the Addresses + // requirement that all Listeners are available on all assigned + // addresses. + // + // Compatible combinations in Extended support are expected to vary across + // implementations. A combination that is compatible for one implementation + // may not be compatible for another. + // + // For example, an implementation that cannot serve both TCP and UDP listeners + // on the same address, or cannot mix HTTPS and generic TLS listens on the same port + // would not consider those cases compatible, even though they are distinct. + // + // Note that requests SHOULD match at most one Listener. For example, if + // Listeners are defined for "foo.example.com" and "*.example.com", a + // request to "foo.example.com" SHOULD only be routed using routes attached + // to the "foo.example.com" Listener (and not the "*.example.com" Listener). + // This concept is known as "Listener Isolation". Implementations that do + // not support Listener Isolation MUST clearly document this. + // + // Implementations MAY merge separate Gateways onto a single set of + // Addresses if all Listeners across all Gateways are compatible. + // + // Support: Core + // + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=64 + // +kubebuilder:validation:XValidation:message="tls must be specified for protocols ['HTTPS', 'TLS']",rule="self.all(l, l.protocol in ['HTTPS', 'TLS'] ? has(l.tls) : true)" + // +kubebuilder:validation:XValidation:message="tls must not be specified for protocols ['HTTP', 'TCP', 'UDP']",rule="self.all(l, l.protocol in ['HTTP', 'TCP', 'UDP'] ? !has(l.tls) : true)" + // +kubebuilder:validation:XValidation:message="hostname must not be specified for protocols ['TCP', 'UDP']",rule="self.all(l, l.protocol in ['TCP', 'UDP'] ? (!has(l.hostname) || l.hostname == '') : true)" + // +kubebuilder:validation:XValidation:message="Listener name must be unique within the Gateway",rule="self.all(l1, self.exists_one(l2, l1.name == l2.name))" + // +kubebuilder:validation:XValidation:message="Combination of port, protocol and hostname must be unique for each listener",rule="self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))" + Listeners []Listener `json:"listeners"` + + // 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. + // + // 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. + // + // If no Addresses are specified, the implementation MAY schedule the + // Gateway in an implementation-specific manner, assigning an appropriate + // set of Addresses. + // + // The implementation MUST bind all Listeners to every GatewayAddress that + // it assigns to the Gateway and add a corresponding entry in + // GatewayStatus.Addresses. + // + // Support: Extended + // + // +optional + // + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:validation:XValidation:message="IPAddress values must be unique",rule="self.all(a1, a1.type == 'IPAddress' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )" + // +kubebuilder:validation:XValidation:message="Hostname values must be unique",rule="self.all(a1, a1.type == 'Hostname' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )" + Addresses []GatewayAddress `json:"addresses,omitempty"` + + // Infrastructure defines infrastructure level attributes about this Gateway instance. + // + // Support: Core + // + // + // +optional + Infrastructure GatewayInfrastructure `json:"infrastructure,omitempty"` +} + +// Listener embodies the concept of a logical endpoint where a Gateway accepts +// network connections. +type Listener struct { + // Name is the name of the Listener. This name MUST be unique within a + // Gateway. + // + // Support: Core + Name SectionName `json:"name"` + + // 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. + // + // 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 + // accepted. For more information, refer to the Route specific Hostnames + // documentation. + // + // Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + // as a suffix match. That means that a match for `*.example.com` would match + // both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + // + // Support: Core + // + // +optional + Hostname *Hostname `json:"hostname,omitempty"` + + // Port is the network port. Multiple listeners may use the + // same port, subject to the Listener compatibility rules. + // + // Support: Core + Port PortNumber `json:"port"` + + // Protocol specifies the network protocol this listener expects to receive. + // + // Support: Core + Protocol ProtocolType `json:"protocol"` + + // 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". + // + // The association of SNIs to Certificate defined in GatewayTLSConfig is + // defined based on the Hostname field for this listener. + // + // The GatewayClass MUST use the longest matching SNI out of all + // available certificates for any TLS handshake. + // + // Support: Core + // + // +optional + TLS *GatewayTLSConfig `json:"tls,omitempty"` + + // AllowedRoutes defines the types of routes that MAY be attached to a + // Listener and the trusted namespaces where those Route resources MAY be + // present. + // + // 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: + // + // * 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. + // + // 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. + // + // Support: Core + // +kubebuilder:default={namespaces:{from: Same}} + // +optional + AllowedRoutes *AllowedRoutes `json:"allowedRoutes,omitempty"` +} + +// ProtocolType defines the application protocol accepted by a Listener. +// Implementations are not required to accept all the defined protocols. If an +// implementation does not support a specified protocol, it MUST set the +// "Accepted" condition to False for the affected Listener with a reason of +// "UnsupportedProtocol". +// +// Core ProtocolType values are listed in the table below. +// +// Implementations can define their own protocols if a core ProtocolType does not +// exist. Such definitions must use prefixed name, such as +// `mycompany.com/my-custom-protocol`. Un-prefixed names are reserved for core +// protocols. Any protocol defined by implementations will fall under +// Implementation-specific conformance. +// +// Valid values include: +// +// * "HTTP" - Core support +// * "example.com/bar" - Implementation-specific support +// +// Invalid values include: +// +// * "example.com" - must include path if domain is used +// * "foo.example.com" - must include path if domain is used +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=255 +// +kubebuilder:validation: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 ProtocolType string + +const ( + // Accepts cleartext HTTP/1.1 sessions over TCP. Implementations MAY also + // support HTTP/2 over cleartext. If implementations support HTTP/2 over + // cleartext on "HTTP" listeners, that MUST be clearly documented by the + // implementation. + HTTPProtocolType ProtocolType = "HTTP" + + // Accepts HTTP/1.1 or HTTP/2 sessions over TLS. + HTTPSProtocolType ProtocolType = "HTTPS" + + // Accepts TLS sessions over TCP. + TLSProtocolType ProtocolType = "TLS" + + // Accepts TCP sessions. + TCPProtocolType ProtocolType = "TCP" + + // Accepts UDP packets. + UDPProtocolType ProtocolType = "UDP" +) + +// GatewayTLSConfig describes a TLS configuration. +// +// +kubebuilder:validation:XValidation:message="certificateRefs must be specified when TLSModeType is Terminate",rule="self.mode == 'Terminate' ? size(self.certificateRefs) > 0 : true" +type GatewayTLSConfig struct { + // 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 + // 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. + // + // Support: Core + // + // +optional + // +kubebuilder:default=Terminate + Mode *TLSModeType `json:"mode,omitempty"` + + // 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. + // + // 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. + // + // References to a resource in different namespace are invalid UNLESS there + // is a ReferenceGrant in the target namespace that allows the certificate + // to be attached. If a ReferenceGrant does not allow this reference, the + // "ResolvedRefs" condition MUST be set to False for this listener with the + // "RefNotPermitted" reason. + // + // This field is required to have at least one element when the mode is set + // to "Terminate" (default) and is optional otherwise. + // + // CertificateRefs can reference to standard Kubernetes resources, i.e. + // Secret, or implementation-specific custom resources. + // + // Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls + // + // Support: Implementation-specific (More than one reference or other resource types) + // + // +optional + // +kubebuilder:validation:MaxItems=64 + CertificateRefs []SecretObjectReference `json:"certificateRefs,omitempty"` + + // 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. + // + // 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. + // + // Support: Implementation-specific + // + // +optional + // +kubebuilder:validation:MaxProperties=16 + Options map[AnnotationKey]AnnotationValue `json:"options,omitempty"` +} + +// TLSModeType type defines how a Gateway handles TLS sessions. +// +// +kubebuilder:validation:Enum=Terminate;Passthrough +type TLSModeType string + +const ( + // In this mode, TLS session between the downstream client + // and the Gateway is terminated at the Gateway. + TLSModeTerminate TLSModeType = "Terminate" + + // In this mode, 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. + // + // Note that SSL passthrough is only supported by TLSRoute. + TLSModePassthrough TLSModeType = "Passthrough" +) + +// AllowedRoutes defines which Routes may be attached to this Listener. +type AllowedRoutes struct { + // Namespaces indicates namespaces from which Routes may be attached to this + // Listener. This is restricted to the namespace of this Gateway by default. + // + // Support: Core + // + // +optional + // +kubebuilder:default={from: Same} + Namespaces *RouteNamespaces `json:"namespaces,omitempty"` + + // 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. + // + // 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 + // "InvalidRouteKinds" reason. + // + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=8 + Kinds []RouteGroupKind `json:"kinds,omitempty"` +} + +// FromNamespaces specifies namespace from which Routes may be attached to a +// Gateway. +// +// +kubebuilder:validation:Enum=All;Selector;Same +type FromNamespaces string + +const ( + // Routes in all namespaces may be attached to this Gateway. + NamespacesFromAll FromNamespaces = "All" + // Only Routes in namespaces selected by the selector may be attached to + // this Gateway. + NamespacesFromSelector FromNamespaces = "Selector" + // Only Routes in the same namespace as the Gateway may be attached to this + // Gateway. + NamespacesFromSame FromNamespaces = "Same" +) + +// RouteNamespaces indicate which namespaces Routes should be selected from. +type RouteNamespaces struct { + // 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. + // + // Support: Core + // + // +optional + // +kubebuilder:default=Same + From *FromNamespaces `json:"from,omitempty"` + + // 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". + // + // Support: Core + // + // +optional + Selector *metav1.LabelSelector `json:"selector,omitempty"` +} + +// RouteGroupKind indicates the group and kind of a Route resource. +type RouteGroupKind struct { + // Group is the group of the Route. + // + // +optional + // +kubebuilder:default=gateway.networking.k8s.io + Group *Group `json:"group,omitempty"` + + // Kind is the kind of the Route. + Kind Kind `json:"kind"` +} + +// GatewayAddress describes an address that can be bound to a Gateway. +// +// +kubebuilder:validation:XValidation:message="Hostname value must only contain valid characters (matching ^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$)",rule="self.type == 'Hostname' ? self.value.matches(r\"\"\"^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$\"\"\"): true" +type GatewayAddress struct { + // Type of the address. + // + // +optional + // +kubebuilder:default=IPAddress + Type *AddressType `json:"type,omitempty"` + + // Value of the address. The validity of the values will depend + // on the type and support by the controller. + // + // Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Value string `json:"value"` +} + +// GatewayStatusAddress describes a network address that is bound to a Gateway. +// +// +kubebuilder:validation:XValidation:message="Hostname value must only contain valid characters (matching ^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$)",rule="self.type == 'Hostname' ? self.value.matches(r\"\"\"^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$\"\"\"): true" +type GatewayStatusAddress struct { + // Type of the address. + // + // +optional + // +kubebuilder:default=IPAddress + Type *AddressType `json:"type,omitempty"` + + // Value of the address. The validity of the values will depend + // on the type and support by the controller. + // + // Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Value string `json:"value"` +} + +// GatewayStatus defines the observed state of Gateway. +type GatewayStatus struct { + // Addresses lists the network addresses that have been bound to the + // Gateway. + // + // This list may differ from the addresses provided in the spec under some + // conditions: + // + // * no addresses are specified, all addresses are dynamically assigned + // * a combination of specified and dynamic addresses are assigned + // * a specified address was unusable (e.g. already in use) + // + // +optional + // + // +kubebuilder:validation:MaxItems=16 + Addresses []GatewayStatusAddress `json:"addresses,omitempty"` + + // Conditions describe the current conditions of the Gateway. + // + // 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. + // + // Known condition types are: + // + // * "Accepted" + // * "Programmed" + // * "Ready" + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:default={{type: "Accepted", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type: "Programmed", status: "Unknown", reason:"Pending", 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. + // + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=64 + Listeners []ListenerStatus `json:"listeners,omitempty"` +} + +// GatewayInfrastructure defines infrastructure level attributes about a Gateway instance. +type GatewayInfrastructure struct { + // Labels that SHOULD be applied to any resources created in response to this Gateway. + // + // For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources. + // For other implementations, this refers to any relevant (implementation specific) "labels" concepts. + // + // An implementation may chose to add additional implementation-specific labels as they see fit. + // + // Support: Extended + // +kubebuilder:validation:MaxProperties=8 + Labels map[AnnotationKey]AnnotationValue `json:"labels,omitempty"` + + // Annotations that SHOULD be applied to any resources created in response to this Gateway. + // + // For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources. + // For other implementations, this refers to any relevant (implementation specific) "annotations" concepts. + // + // An implementation may chose to add additional implementation-specific annotations as they see fit. + // + // Support: Extended + // +kubebuilder:validation:MaxProperties=8 + Annotations map[AnnotationKey]AnnotationValue `json:"annotations,omitempty"` +} + +// GatewayConditionType is a type of condition associated with a +// Gateway. This type should be used with the GatewayStatus.Conditions +// field. +type GatewayConditionType string + +// GatewayConditionReason defines the set of reasons that explain why a +// particular Gateway condition type has been raised. +type GatewayConditionReason string + +const ( + // This condition indicates whether a Gateway has generated some + // configuration that is assumed to be ready soon in the underlying data + // plane. + // + // It is a positive-polarity summary condition, and so should always be + // present on the resource with ObservedGeneration set. + // + // It should be set to Unknown if the controller performs updates to the + // status before it has all the information it needs to be able to determine + // if the condition is true. + // + // Possible reasons for this condition to be True are: + // + // * "Programmed" + // + // Possible reasons for this condition to be False are: + // + // * "Invalid" + // * "Pending" + // * "NoResources" + // * "AddressNotAssigned" + // + // Possible reasons for this condition to be Unknown are: + // + // * "Pending" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + GatewayConditionProgrammed GatewayConditionType = "Programmed" + + // This reason is used with the "Programmed" condition when the condition is + // true. + GatewayReasonProgrammed GatewayConditionReason = "Programmed" + + // This reason is used with the "Programmed" and "Accepted" conditions when the Gateway is + // syntactically or semantically invalid. + GatewayReasonInvalid GatewayConditionReason = "Invalid" + + // This reason is used with the "Programmed" condition when the + // Gateway is not scheduled because insufficient infrastructure + // resources are available. + GatewayReasonNoResources GatewayConditionReason = "NoResources" + + // This reason is used with the "Programmed" condition when the underlying + // implementation and network have yet to dynamically assign addresses for a + // Gateway. + // + // Some example situations where this reason can be used: + // + // * IPAM address exhaustion + // * Address not yet allocated + // + // When this reason is used the implementation SHOULD provide a clear + // message explaining the underlying problem, ideally with some hints as to + // what actions can be taken that might resolve the problem. + GatewayReasonAddressNotAssigned GatewayConditionReason = "AddressNotAssigned" + + // This reason is used with the "Programmed" condition when the underlying + // implementation (and possibly, network) are unable to use an address that + // was provided in the Gateway specification. + // + // Some example situations where this reason can be used: + // + // * a named address not being found + // * a provided static address can't be used + // * the address is already in use + // + // When this reason is used the implementation SHOULD provide prescriptive + // information on which address is causing the problem and how to resolve it + // in the condition message. + GatewayReasonAddressNotUsable GatewayConditionReason = "AddressNotUsable" +) + +const ( + // This condition is true when the controller managing the Gateway is + // syntactically and semantically valid enough to produce some configuration + // in the underlying data plane. This does not indicate whether or not the + // configuration has been propagated to the data plane. + // + // Possible reasons for this condition to be True are: + // + // * "Accepted" + // * "ListenersNotValid" + // + // Possible reasons for this condition to be False are: + // + // * "Invalid" + // * "NotReconciled" + // * "UnsupportedAddress" + // * "ListenersNotValid" + // + // Possible reasons for this condition to be Unknown are: + // + // * "Pending" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + GatewayConditionAccepted GatewayConditionType = "Accepted" + + // This reason is used with the "Accepted" condition when the condition is + // True. + GatewayReasonAccepted GatewayConditionReason = "Accepted" + + // This reason is used with the "Accepted" condition when one or + // more Listeners have an invalid or unsupported configuration + // and cannot be configured on the Gateway. + // This can be the reason when "Accepted" is "True" or "False", depending on whether + // the listener being invalid causes the entire Gateway to not be accepted. + GatewayReasonListenersNotValid GatewayConditionReason = "ListenersNotValid" + + // This reason is used with the "Accepted" and "Programmed" + // conditions when the status is "Unknown" and no controller has reconciled + // the Gateway. + GatewayReasonPending GatewayConditionReason = "Pending" + + // This reason is used with the "Accepted" condition to indicate that the + // Gateway could not be accepted because an address that was provided is a + // type which is not supported by the implementation. + GatewayReasonUnsupportedAddress GatewayConditionReason = "UnsupportedAddress" +) + +const ( + // Deprecated: use "Accepted" instead. + GatewayConditionScheduled GatewayConditionType = "Scheduled" + + // This reason is used with the "Scheduled" condition when the condition is + // True. + // + // Deprecated: use the "Accepted" condition with reason "Accepted" instead. + GatewayReasonScheduled GatewayConditionReason = "Scheduled" + + // Deprecated: Use "Pending" instead. + GatewayReasonNotReconciled GatewayConditionReason = "NotReconciled" +) + +const ( + // "Ready" is a condition type reserved for future use. It should not be used by implementations. + // + // If used in the future, "Ready" will represent the final state where all configuration is confirmed good + // _and has completely propagated to the data plane_. That is, it is a _guarantee_ that, as soon as something + // sees the Condition as `true`, then connections will be correctly routed _immediately_. + // + // This is a very strong guarantee, and to date no implementation has satisfied it enough to implement it. + // This reservation can be discussed in the future if necessary. + // + // Note: This condition is not really "deprecated", but rather "reserved"; however, deprecated triggers Go linters + // to alert about usage. + // Deprecated: Ready is reserved for future use + GatewayConditionReady GatewayConditionType = "Ready" + + // Deprecated: Ready is reserved for future use + GatewayReasonReady GatewayConditionReason = "Ready" + + // Deprecated: Ready is reserved for future use + GatewayReasonListenersNotReady GatewayConditionReason = "ListenersNotReady" +) + +// ListenerStatus is the status associated with a Listener. +type ListenerStatus struct { + // Name is the name of the Listener that this status corresponds to. + Name SectionName `json:"name"` + + // SupportedKinds is the list indicating the Kinds supported by this + // 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"` + + // AttachedRoutes represents the total number of Routes that have been + // successfully attached to this Listener. + // + // Successful attachment of a Route to a Listener is based solely on the + // combination of the AllowedRoutes field on the corresponding Listener + // and the Route's ParentRefs field. A Route is successfully attached to + // a Listener when it is selected by the Listener's AllowedRoutes field + // AND the Route has a valid ParentRef selecting the whole Gateway + // resource or a specific Listener as a parent resource (more detail on + // attachment semantics can be found in the documentation on the various + // Route kinds ParentRefs fields). Listener or Route status does not impact + // successful attachment, i.e. the AttachedRoutes field count MUST be set + // for Listeners with condition Accepted: false and MUST count successfully + // attached Routes that may themselves have Accepted: false conditions. + // + // Uses for this field include troubleshooting Route attachment and + // measuring blast radius/impact of changes to a Listener. + AttachedRoutes int32 `json:"attachedRoutes"` + + // Conditions describe the current condition of this listener. + // + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions"` +} + +// ListenerConditionType is a type of condition associated with the +// listener. This type should be used with the ListenerStatus.Conditions +// field. +type ListenerConditionType string + +// ListenerConditionReason defines the set of reasons that explain +// why a particular Listener condition type has been raised. +type ListenerConditionReason string + +const ( + // This condition indicates that the controller was unable to resolve + // conflicting specification requirements for this Listener. If a + // Listener is conflicted, its network port should not be configured + // on any network elements. + // + // Possible reasons for this condition to be true are: + // + // * "HostnameConflict" + // * "ProtocolConflict" + // + // Possible reasons for this condition to be False are: + // + // * "NoConflicts" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + ListenerConditionConflicted ListenerConditionType = "Conflicted" + + // This reason is used with the "Conflicted" condition when + // the Listener conflicts with hostnames in other Listeners. For + // example, this reason would be used when multiple Listeners on + // the same port use `example.com` in the hostname field. + ListenerReasonHostnameConflict ListenerConditionReason = "HostnameConflict" + + // This reason is used with the "Conflicted" condition when + // multiple Listeners are specified with the same Listener port + // number, but have conflicting protocol specifications. + ListenerReasonProtocolConflict ListenerConditionReason = "ProtocolConflict" + + // This reason is used with the "Conflicted" condition when the condition + // is False. + ListenerReasonNoConflicts ListenerConditionReason = "NoConflicts" +) + +const ( + // This condition indicates that the listener is syntactically and + // semantically valid, and that all features used in the listener's spec are + // supported. + // + // In general, a Listener will be marked as Accepted when the supplied + // configuration will generate at least some data plane configuration. + // + // For example, a Listener with an unsupported protocol will never generate + // any data plane config, and so will have Accepted set to `false.` + // Conversely, a Listener that does not have any Routes will be able to + // generate data plane config, and so will have Accepted set to `true`. + // + // Possible reasons for this condition to be True are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "PortUnavailable" + // * "UnsupportedProtocol" + // + // Possible reasons for this condition to be Unknown are: + // + // * "Pending" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + ListenerConditionAccepted ListenerConditionType = "Accepted" + + // Deprecated: use "Accepted" instead. + ListenerConditionDetached ListenerConditionType = "Detached" + + // This reason is used with the "Accepted" condition when the condition is + // True. + ListenerReasonAccepted ListenerConditionReason = "Accepted" + + // This reason is used with the "Detached" condition when the condition is + // False. + // + // Deprecated: use the "Accepted" condition with reason "Accepted" instead. + ListenerReasonAttached ListenerConditionReason = "Attached" + + // This reason is used with the "Accepted" 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 "Accepted" condition when the + // Listener could not be attached to be Gateway because its + // protocol type is not supported. + ListenerReasonUnsupportedProtocol ListenerConditionReason = "UnsupportedProtocol" +) + +const ( + // This condition indicates whether the controller was able to + // resolve all the object references for the Listener. + // + // Possible reasons for this condition to be true are: + // + // * "ResolvedRefs" + // + // Possible reasons for this condition to be False are: + // + // * "InvalidCertificateRef" + // * "InvalidRouteKinds" + // * "RefNotPermitted" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + ListenerConditionResolvedRefs ListenerConditionType = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the condition + // is true. + ListenerReasonResolvedRefs ListenerConditionReason = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the + // Listener has a TLS configuration with at least one TLS CertificateRef + // that is invalid or does not exist. + // A CertificateRef is considered invalid when it refers to a nonexistent + // or unsupported resource or kind, or when the data within that resource + // is malformed. + // This reason must be used only when the reference is allowed, either by + // referencing an object in the same namespace as the Gateway, or when + // a cross-namespace reference has been explicitly allowed by a ReferenceGrant. + // If the reference is not allowed, the reason RefNotPermitted must be used + // instead. + ListenerReasonInvalidCertificateRef ListenerConditionReason = "InvalidCertificateRef" + + // This reason is used with the "ResolvedRefs" condition when an invalid or + // unsupported Route kind is specified by the Listener. + ListenerReasonInvalidRouteKinds ListenerConditionReason = "InvalidRouteKinds" + + // This reason is used with the "ResolvedRefs" condition when the + // Listener has a TLS configuration that references an object in another + // namespace, where the object in the other namespace does not have a + // ReferenceGrant explicitly allowing the reference. + ListenerReasonRefNotPermitted ListenerConditionReason = "RefNotPermitted" +) + +const ( + // This condition indicates whether a Listener has generated some + // configuration that will soon be ready in the underlying data plane. + // + // It is a positive-polarity summary condition, and so should always be + // present on the resource with ObservedGeneration set. + // + // It should be set to Unknown if the controller performs updates to the + // status before it has all the information it needs to be able to determine + // if the condition is true. + // + // Possible reasons for this condition to be True are: + // + // * "Programmed" + // + // Possible reasons for this condition to be False are: + // + // * "Invalid" + // * "Pending" + // + // Possible reasons for this condition to be Unknown are: + // + // * "Pending" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + ListenerConditionProgrammed ListenerConditionType = "Programmed" + + // This reason is used with the "Programmed" condition when the condition is + // true. + ListenerReasonProgrammed ListenerConditionReason = "Programmed" + + // This reason is used with the "Ready" and "Programmed" conditions when the + // Listener is syntactically or semantically invalid. + ListenerReasonInvalid ListenerConditionReason = "Invalid" + + // This reason is used with the "Accepted", "Ready" and "Programmed" + // conditions when the Listener is either not yet reconciled or not yet not + // online and ready to accept client traffic. + ListenerReasonPending ListenerConditionReason = "Pending" +) + +const ( + // "Ready" is a condition type reserved for future use. It should not be used by implementations. + // Note: This condition is not really "deprecated", but rather "reserved"; however, deprecated triggers Go linters + // to alert about usage. + // + // If used in the future, "Ready" will represent the final state where all configuration is confirmed good + // _and has completely propagated to the data plane_. That is, it is a _guarantee_ that, as soon as something + // sees the Condition as `true`, then connections will be correctly routed _immediately_. + // + // This is a very strong guarantee, and to date no implementation has satisfied it enough to implement it. + // This reservation can be discussed in the future if necessary. + // + // Deprecated: Ready is reserved for future use + ListenerConditionReady ListenerConditionType = "Ready" + + // Deprecated: Ready is reserved for future use + ListenerReasonReady ListenerConditionReason = "Ready" +) diff --git a/apis/v1/gatewayclass_types.go b/apis/v1/gatewayclass_types.go new file mode 100644 index 0000000000..f219a0a2f2 --- /dev/null +++ b/apis/v1/gatewayclass_types.go @@ -0,0 +1,268 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=gateway-api,scope=Cluster,shortName=gc +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Controller",type=string,JSONPath=`.spec.controllerName` +// +kubebuilder:printcolumn:name="Accepted",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].status` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:printcolumn:name="Description",type=string,JSONPath=`.spec.description`,priority=1 + +// GatewayClass describes a class of Gateways available to the user for creating +// Gateway resources. +// +// 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. +// +// Whenever one or more Gateways are using a GatewayClass, implementations SHOULD +// 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. +// +// GatewayClass is a Cluster level resource. +type GatewayClass struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of GatewayClass. + Spec GatewayClassSpec `json:"spec"` + + // Status defines the current state of GatewayClass. + // + // Implementations MUST populate status on all GatewayClass resources which + // specify their controller name. + // + // +kubebuilder:default={conditions: {{type: "Accepted", status: "Unknown", message: "Waiting for controller", reason: "Waiting", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + Status GatewayClassStatus `json:"status,omitempty"` +} + +const ( + // GatewayClassFinalizerGatewaysExist should be added as a finalizer to the + // GatewayClass whenever there are provisioned Gateways using a + // GatewayClass. + GatewayClassFinalizerGatewaysExist = "gateway-exists-finalizer.gateway.networking.k8s.io" +) + +// GatewayClassSpec reflects the configuration of a class of Gateways. +type GatewayClassSpec struct { + // 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. + // + // Support: Core + // + // +kubebuilder:validation:XValidation:message="Value is immutable",rule="self == oldSelf" + 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 + // controller does not require any additional configuration. + // + // 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. + // + // If the referent cannot be found, the GatewayClass's "InvalidParameters" + // status condition will be true. + // + // Support: Implementation-specific + // + // +optional + ParametersRef *ParametersReference `json:"parametersRef,omitempty"` + + // Description helps describe a GatewayClass with more details. + // + // +kubebuilder:validation:MaxLength=64 + // +optional + Description *string `json:"description,omitempty"` +} + +// ParametersReference identifies an API object containing controller-specific +// configuration resource within the cluster. +type ParametersReference struct { + // Group is the group of the referent. + Group Group `json:"group"` + + // Kind is kind of the referent. + Kind Kind `json:"kind"` + + // Name is the name of the referent. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Name string `json:"name"` + + // 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. + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` +} + +// GatewayClassConditionType is the type for status conditions on +// Gateway resources. This type should be used with the +// GatewayClassStatus.Conditions field. +type GatewayClassConditionType string + +// GatewayClassConditionReason defines the set of reasons that explain why a +// particular GatewayClass condition type has been raised. +type GatewayClassConditionReason string + +const ( + // This condition indicates whether the GatewayClass has been accepted by + // the controller requested in the `spec.controller` field. + // + // 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: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "InvalidParameters" + // * "UnsupportedVersion" + // + // Possible reasons for this condition to be Unknown are: + // + // * "Pending" + // + // Controllers should prefer to use the values of GatewayClassConditionReason + // for the corresponding Reason, where appropriate. + GatewayClassConditionStatusAccepted GatewayClassConditionType = "Accepted" + + // This reason is used with the "Accepted" condition when the condition is + // true. + GatewayClassReasonAccepted GatewayClassConditionReason = "Accepted" + + // 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 "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. + GatewayClassReasonPending GatewayClassConditionReason = "Pending" + + // Deprecated: Use "Pending" instead. + GatewayClassReasonWaiting GatewayClassConditionReason = "Waiting" +) + +const ( + // This condition indicates whether the GatewayClass supports the version(s) + // of Gateway API CRDs present in the cluster. This condition MUST be set by + // a controller when it marks a GatewayClass "Accepted". + // + // The version of a Gateway API CRD is defined by the + // gateway.networking.k8s.io/bundle-version annotation on the CRD. If + // implementations detect any Gateway API CRDs that either do not have this + // annotation set, or have it set to a version that is not recognized or + // supported by the implementation, this condition MUST be set to false. + // + // Implementations MAY choose to either provide "best effort" support when + // an unrecognized CRD version is present. This would be communicated by + // setting the "Accepted" condition to true and the "SupportedVersion" + // condition to false. + // + // Alternatively, implementations MAY choose not to support CRDs with + // unrecognized versions. This would be communicated by setting the + // "Accepted" condition to false with the reason "UnsupportedVersions". + // + // Possible reasons for this condition to be true are: + // + // * "SupportedVersion" + // + // Possible reasons for this condition to be False are: + // + // * "UnsupportedVersion" + // + // Controllers should prefer to use the values of GatewayClassConditionReason + // for the corresponding Reason, where appropriate. + GatewayClassConditionStatusSupportedVersion GatewayClassConditionType = "SupportedVersion" + + // This reason is used with the "SupportedVersion" condition when the + // condition is true. + GatewayClassReasonSupportedVersion GatewayClassConditionReason = "SupportedVersion" + + // This reason is used with the "SupportedVersion" or "Accepted" condition + // when the condition is false. A message SHOULD be included in this + // condition that includes the detected CRD version(s) present in the + // cluster and the CRD version(s) that are supported by the GatewayClass. + GatewayClassReasonUnsupportedVersion GatewayClassConditionReason = "UnsupportedVersion" +) + +// GatewayClassStatus is the current status for the GatewayClass. +type GatewayClassStatus struct { + // Conditions is the current status from the controller for + // this GatewayClass. + // + // Controllers should prefer to publish conditions using values + // of GatewayClassConditionType for the type of each Condition. + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:default={{type: "Accepted", status: "Unknown", message: "Waiting for controller", reason: "Pending", lastTransitionTime: "1970-01-01T00:00:00Z"}} + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // SupportedFeatures is the set of features the GatewayClass support. + // It MUST be sorted in ascending alphabetical order. + // +optional + // +listType=set + // + // +kubebuilder:validation:MaxItems=64 + SupportedFeatures []SupportedFeature `json:"supportedFeatures,omitempty"` +} + +// +kubebuilder:object:root=true + +// GatewayClassList contains a list of GatewayClass +type GatewayClassList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []GatewayClass `json:"items"` +} + +// SupportedFeature is used to describe distinct features that are covered by +// conformance tests. +// +kubebuilder:validation:Enum=Gateway;GatewayPort8080;GatewayStaticAddresses;HTTPRoute;HTTPRouteDestinationPortMatching;HTTPRouteHostRewrite;HTTPRouteMethodMatching;HTTPRoutePathRedirect;HTTPRoutePathRewrite;HTTPRoutePortRedirect;HTTPRouteQueryParamMatching;HTTPRouteRequestMirror;HTTPRouteRequestMultipleMirrors;HTTPRouteResponseHeaderModification;HTTPRouteSchemeRedirect;Mesh;ReferenceGrant;TLSRoute +type SupportedFeature string diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go new file mode 100644 index 0000000000..816551edfa --- /dev/null +++ b/apis/v1/httproute_types.go @@ -0,0 +1,1201 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=gateway-api +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Hostnames",type=string,JSONPath=`.spec.hostnames` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// 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"` + + // Spec defines the desired state of HTTPRoute. + Spec HTTPRouteSpec `json:"spec"` + + // Status defines the current state of HTTPRoute. + Status HTTPRouteStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// HTTPRouteList contains a list of HTTPRoute. +type HTTPRouteList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []HTTPRoute `json:"items"` +} + +// HTTPRouteSpec defines the desired state of HTTPRoute +type HTTPRouteSpec struct { + CommonRouteSpec `json:",inline"` + + // Hostnames defines a set of hostnames that should match against the HTTP Host + // header to select a HTTPRoute used to process the request. Implementations + // MUST ignore any port value specified in the HTTP Host header while + // performing a match and (absent of any applicable header modification + // configuration) MUST forward this header unmodified to the backend. + // + // Valid values for Hostnames are determined by RFC 1123 definition of a + // hostname with 2 notable exceptions: + // + // 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. + // + // 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: + // + // * 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, + // `*.example.com`, `test.example.com`, and `foo.test.example.com` would + // all match. On the other hand, `example.com` and `test.example.net` would + // not match. + // + // Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + // as a suffix match. That means that a match for `*.example.com` would match + // both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + // + // 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. + // + // 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. + // + // In the event that multiple HTTPRoutes specify intersecting hostnames (e.g. + // overlapping wildcard matching and exact matching hostnames), precedence must + // be given to rules from the HTTPRoute with the largest number of: + // + // * Characters in a matching non-wildcard hostname. + // * Characters in a matching hostname. + // + // If ties exist across multiple Routes, the matching precedence rules for + // HTTPRouteMatches takes over. + // + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Hostnames []Hostname `json:"hostnames,omitempty"` + + // Rules are a list of HTTP matchers, filters and actions. + // + // +optional + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:default={{matches: {{path: {type: "PathPrefix", value: "/"}}}}} + Rules []HTTPRouteRule `json:"rules,omitempty"` +} + +// HTTPRouteRule defines semantics for matching an HTTP request based on +// conditions (matches), processing it (filters), and forwarding the request to +// an API object (backendRefs). +// +// +kubebuilder:validation:XValidation:message="RequestRedirect filter must not be used together with backendRefs",rule="(has(self.backendRefs) && size(self.backendRefs) > 0) ? (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): true" +// +kubebuilder:validation:XValidation:message="When using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified",rule="(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == 'ReplacePrefixMatch' && has(f.requestRedirect.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" +// +kubebuilder:validation:XValidation:message="When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified",rule="(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == 'ReplacePrefixMatch' && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" +// +kubebuilder:validation:XValidation:message="Within backendRefs, when using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified",rule="(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == 'ReplacePrefixMatch' && has(f.requestRedirect.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" +// +kubebuilder:validation:XValidation:message="Within backendRefs, When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified",rule="(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == 'ReplacePrefixMatch' && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" +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 + // if **any** one of the matches is satisfied. + // + // For example, take the following matches configuration: + // + // ``` + // matches: + // - path: + // value: "/foo" + // headers: + // - name: "version" + // value: "v2" + // - path: + // value: "/v2/foo" + // ``` + // + // For a request to match against this rule, a request must satisfy + // EITHER of the two conditions: + // + // - path prefixed with `/foo` AND contains the header `version: v2` + // - path prefix of `/v2/foo` + // + // See the documentation for HTTPRouteMatch on how to specify multiple + // match conditions that should be ANDed together. + // + // If no matches are specified, the default is a prefix + // path match on "/", which has the effect of matching every + // HTTP request. + // + // Proxy or Load Balancer routing configuration generated from HTTPRoutes + // MUST prioritize matches based on the following criteria, continuing on + // ties. Across all rules specified on applicable Routes, precedence must be + // given to the match having: + // + // * "Exact" path match. + // * "Prefix" path match with largest number of characters. + // * Method match. + // * Largest number of header matches. + // * Largest number of query param matches. + // + // Note: The precedence of RegularExpression path matches are implementation-specific. + // + // 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. + // * The Route appearing first in alphabetical order by + // "{namespace}/{name}". + // + // If ties still exist within an HTTPRoute, matching precedence MUST be granted + // to the FIRST matching rule (in list order) with a match meeting the above + // criteria. + // + // When no rules matching a request have been successfully attached to the + // parent a request is coming from, a HTTP 404 status code MUST be returned. + // + // +optional + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:default={{path:{ type: "PathPrefix", value: "/"}}} + Matches []HTTPRouteMatch `json:"matches,omitempty"` + + // Filters define the filters that are applied to requests that match + // this rule. + // + // The effects of ordering of multiple behaviors are currently unspecified. + // This can change in the future based on feedback during the alpha stage. + // + // Conformance-levels at this level are defined based on the type of filter: + // + // - 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. + // + // Specifying the same filter multiple times is not supported unless explicitly + // indicated in the filter. + // + // All filters are expected to be compatible with each other except for the + // URLRewrite and RequestRedirect filters, which may not be combined. If an + // implementation can not support other combinations of filters, they must clearly + // document that limitation. In cases where incompatible or unsupported + // filters are specified and cause the `Accepted` condition to be set to status + // `False`, implementations may use the `IncompatibleFilters` reason to specify + // this configuration error. + // + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:validation:XValidation:message="May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both",rule="!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" + // +kubebuilder:validation:XValidation:message="RequestHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1" + // +kubebuilder:validation:XValidation:message="ResponseHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1" + // +kubebuilder:validation:XValidation:message="RequestRedirect filter cannot be repeated",rule="self.filter(f, f.type == 'RequestRedirect').size() <= 1" + // +kubebuilder:validation:XValidation:message="URLRewrite filter cannot be repeated",rule="self.filter(f, f.type == 'URLRewrite').size() <= 1" + Filters []HTTPRouteFilter `json:"filters,omitempty"` + + // BackendRefs defines the backend(s) where matching requests should be + // sent. + // + // Failure behavior here depends on how many BackendRefs are specified and + // how many are invalid. + // + // If *all* entries in BackendRefs are invalid, and there are also no filters + // specified in this route rule, *all* traffic which matches this rule MUST + // receive a 500 status code. + // + // See the HTTPBackendRef definition for the rules about what makes a single + // HTTPBackendRef invalid. + // + // When a HTTPBackendRef is invalid, 500 status codes MUST be returned for + // requests that would have otherwise been routed to an invalid backend. If + // multiple backends are specified, and some are invalid, the proportion of + // requests that would otherwise have been routed to an invalid backend + // MUST receive a 500 status code. + // + // For example, if two backends are specified with equal weights, and one is + // invalid, 50 percent of traffic must receive a 500. Implementations may + // choose how that 50 percent is determined. + // + // Support: Core for Kubernetes Service + // + // Support: Extended for Kubernetes ServiceImport + // + // Support: Implementation-specific for any other resource + // + // Support for weight: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + BackendRefs []HTTPBackendRef `json:"backendRefs,omitempty"` + + // Timeouts defines the timeouts that can be configured for an HTTP request. + // + // Support: Extended + // + // +optional + // + Timeouts *HTTPRouteTimeouts `json:"timeouts,omitempty"` +} + +// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute. +// Timeout values are represented with Gateway API Duration formatting. +// Specifying a zero value such as "0s" is interpreted as no timeout. +// +// +kubebuilder:validation:XValidation:message="backendRequest timeout cannot be longer than request timeout",rule="!(has(self.request) && has(self.backendRequest) && duration(self.request) != duration('0s') && duration(self.backendRequest) > duration(self.request))" +type HTTPRouteTimeouts struct { + // Request specifies the maximum duration for a gateway to respond to an HTTP request. + // If the gateway has not been able to respond before this deadline is met, the gateway + // MUST return a timeout error. + // + // For example, setting the `rules.timeouts.request` field to the value `10s` in an + // `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds + // to complete. + // + // This timeout is intended to cover as close to the whole request-response transaction + // as possible although an implementation MAY choose to start the timeout after the entire + // request stream has been received instead of immediately after the transaction is + // initiated by the client. + // + // When this field is unspecified, request timeout behavior is implementation-specific. + // + // Support: Extended + // + // +optional + Request *Duration `json:"request,omitempty"` + + // BackendRequest specifies a timeout for an individual request from the gateway + // to a backend. This covers the time from when the request first starts being + // sent from the gateway to when the full response has been received from the backend. + // + // An entire client HTTP transaction with a gateway, covered by the Request timeout, + // may result in more than one call from the gateway to the destination backend, + // for example, if automatic retries are supported. + // + // Because the Request timeout encompasses the BackendRequest timeout, the value of + // BackendRequest must be <= the value of Request timeout. + // + // Support: Extended + // + // +optional + BackendRequest *Duration `json:"backendRequest,omitempty"` +} + +// PathMatchType specifies the semantics of how HTTP paths should be compared. +// Valid PathMatchType values, along with their support levels, are: +// +// * "Exact" - Core +// * "PathPrefix" - Core +// * "RegularExpression" - Implementation Specific +// +// PathPrefix and Exact paths must be syntactically valid: +// +// - Must begin with the `/` character +// - Must not contain consecutive `/` characters (e.g. `/foo///`, `//`). +// +// Note that values may be added to this enum, implementations +// must ensure that unknown values will not cause a crash. +// +// Unknown values here must result in the implementation setting the +// Accepted Condition for the Route to `status: False`, with a +// Reason of `UnsupportedValue`. +// +// +kubebuilder:validation:Enum=Exact;PathPrefix;RegularExpression +type PathMatchType string + +const ( + // Matches the URL path exactly and with case sensitivity. This means that + // an exact path match on `/abc` will only match requests to `/abc`, NOT + // `/abc/`, `/Abc`, or `/abcd`. + PathMatchExact PathMatchType = "Exact" + + // Matches based on a URL path prefix split by `/`. Matching is + // case sensitive and done on a path element by element basis. A + // path element refers to the list of labels in the path split by + // the `/` separator. When specified, a trailing `/` is ignored. + // + // For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match + // the prefix `/abc`, but the path `/abcd` would not. + // + // "PathPrefix" is semantically equivalent to the "Prefix" path type in the + // Kubernetes Ingress API. + PathMatchPathPrefix PathMatchType = "PathPrefix" + + // Matches if the URL path matches the given regular expression with + // case sensitivity. + // + // Since `"RegularExpression"` has implementation-specific conformance, + // implementations can support POSIX, PCRE, RE2 or any other regular expression + // dialect. + // Please read the implementation's documentation to determine the supported + // dialect. + PathMatchRegularExpression PathMatchType = "RegularExpression" +) + +// HTTPPathMatch describes how to select a HTTP route by matching the HTTP request path. +// +// +kubebuilder:validation:XValidation:message="value must be an absolute path and start with '/' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? self.value.startsWith('/') : true" +// +kubebuilder:validation:XValidation:message="must not contain '//' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.contains('//') : true" +// +kubebuilder:validation:XValidation:message="must not contain '/./' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.contains('/./') : true" +// +kubebuilder:validation:XValidation:message="must not contain '/../' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.contains('/../') : true" +// +kubebuilder:validation:XValidation:message="must not contain '%2f' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.contains('%2f') : true" +// +kubebuilder:validation:XValidation:message="must not contain '%2F' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.contains('%2F') : true" +// +kubebuilder:validation:XValidation:message="must not contain '#' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.contains('#') : true" +// +kubebuilder:validation:XValidation:message="must not end with '/..' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.endsWith('/..') : true" +// +kubebuilder:validation:XValidation:message="must not end with '/.' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.endsWith('/.') : true" +// +kubebuilder:validation:XValidation:message="type must be one of ['Exact', 'PathPrefix', 'RegularExpression']",rule="self.type in ['Exact','PathPrefix'] || self.type == 'RegularExpression'" +// +kubebuilder:validation:XValidation:message="must only contain valid characters (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) for types ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? self.value.matches(r\"\"\"^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$\"\"\") : true" +type HTTPPathMatch struct { + // Type specifies how to match against the path Value. + // + // Support: Core (Exact, PathPrefix) + // + // Support: Implementation-specific (RegularExpression) + // + // +optional + // +kubebuilder:default=PathPrefix + Type *PathMatchType `json:"type,omitempty"` + + // Value of the HTTP path to match against. + // + // +optional + // +kubebuilder:default="/" + // +kubebuilder:validation:MaxLength=1024 + Value *string `json:"value,omitempty"` +} + +// HeaderMatchType specifies the semantics of how HTTP header values should be +// compared. Valid HeaderMatchType values, along with their conformance levels, are: +// +// * "Exact" - Core +// * "RegularExpression" - Implementation Specific +// +// Note that values may be added to this enum, implementations +// must ensure that unknown values will not cause a crash. +// +// Unknown values here must result in the implementation setting the +// Accepted Condition for the Route to `status: False`, with a +// Reason of `UnsupportedValue`. +// +// +kubebuilder:validation:Enum=Exact;RegularExpression +type HeaderMatchType string + +// HeaderMatchType constants. +const ( + HeaderMatchExact HeaderMatchType = "Exact" + HeaderMatchRegularExpression HeaderMatchType = "RegularExpression" +) + +// HTTPHeaderName is the name of an HTTP header. +// +// Valid values include: +// +// * "Authorization" +// * "Set-Cookie" +// +// Invalid values include: +// +// - ":method" - ":" is an invalid character. This means that HTTP/2 pseudo +// headers are not currently supported by this type. +// - "/invalid" - "/ " is an invalid character +type HTTPHeaderName HeaderName + +// HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request +// headers. +type HTTPHeaderMatch struct { + // Type specifies how to match against the value of the header. + // + // Support: Core (Exact) + // + // Support: Implementation-specific (RegularExpression) + // + // Since RegularExpression HeaderMatchType has implementation-specific + // conformance, implementations can support POSIX, PCRE or any other dialects + // of regular expressions. Please read the implementation's documentation to + // determine the supported dialect. + // + // +optional + // +kubebuilder:default=Exact + Type *HeaderMatchType `json:"type,omitempty"` + + // Name is the name of the HTTP Header to be matched. Name matching MUST be + // case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + // + // If multiple entries specify equivalent header names, 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. + // + // 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". + Name HTTPHeaderName `json:"name"` + + // Value is the value of HTTP Header to be matched. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=4096 + Value string `json:"value"` +} + +// QueryParamMatchType specifies the semantics of how HTTP query parameter +// values should be compared. Valid QueryParamMatchType values, along with their +// conformance levels, are: +// +// * "Exact" - Core +// * "RegularExpression" - Implementation Specific +// +// Note that values may be added to this enum, implementations +// must ensure that unknown values will not cause a crash. +// +// Unknown values here must result in the implementation setting the +// Accepted Condition for the Route to `status: False`, with a +// Reason of `UnsupportedValue`. +// +// +kubebuilder:validation:Enum=Exact;RegularExpression +type QueryParamMatchType string + +// QueryParamMatchType constants. +const ( + QueryParamMatchExact QueryParamMatchType = "Exact" + QueryParamMatchRegularExpression QueryParamMatchType = "RegularExpression" +) + +// HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP +// query parameters. +type HTTPQueryParamMatch struct { + // Type specifies how to match against the value of the query parameter. + // + // Support: Extended (Exact) + // + // Support: Implementation-specific (RegularExpression) + // + // Since RegularExpression QueryParamMatchType has Implementation-specific + // conformance, implementations can support POSIX, PCRE or any other + // dialects of regular expressions. Please read the implementation's + // documentation to determine the supported dialect. + // + // +optional + // +kubebuilder:default=Exact + Type *QueryParamMatchType `json:"type,omitempty"` + + // 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). + // + // If multiple entries specify equivalent query param names, only the first + // entry with an equivalent name MUST be considered for a match. Subsequent + // entries with an equivalent query param name MUST be ignored. + // + // If a query param is repeated in an HTTP request, the behavior is + // purposely left undefined, since different data planes have different + // capabilities. However, it is *recommended* that implementations should + // match against the first value of the param if the data plane supports it, + // as this behavior is expected in other load balancing contexts outside of + // the Gateway API. + // + // Users SHOULD NOT route traffic based on repeated query params to guard + // themselves against potential differences in the implementations. + Name HTTPHeaderName `json:"name"` + + // Value is the value of HTTP query param to be matched. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1024 + Value string `json:"value"` +} + +// HTTPMethod describes how to select a HTTP route by matching the HTTP +// method as defined by +// [RFC 7231](https://datatracker.ietf.org/doc/html/rfc7231#section-4) and +// [RFC 5789](https://datatracker.ietf.org/doc/html/rfc5789#section-2). +// The value is expected in upper case. +// +// Note that values may be added to this enum, implementations +// must ensure that unknown values will not cause a crash. +// +// Unknown values here must result in the implementation setting the +// Accepted Condition for the Route to `status: False`, with a +// Reason of `UnsupportedValue`. +// +// +kubebuilder:validation:Enum=GET;HEAD;POST;PUT;DELETE;CONNECT;OPTIONS;TRACE;PATCH +type HTTPMethod string + +const ( + HTTPMethodGet HTTPMethod = "GET" + HTTPMethodHead HTTPMethod = "HEAD" + HTTPMethodPost HTTPMethod = "POST" + HTTPMethodPut HTTPMethod = "PUT" + HTTPMethodDelete HTTPMethod = "DELETE" + HTTPMethodConnect HTTPMethod = "CONNECT" + HTTPMethodOptions HTTPMethod = "OPTIONS" + HTTPMethodTrace HTTPMethod = "TRACE" + HTTPMethodPatch HTTPMethod = "PATCH" +) + +// 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. +// +// For example, the match below will match a HTTP request only if its path +// starts with `/foo` AND it contains the `version: v1` header: +// +// ``` +// match: +// +// path: +// value: "/foo" +// headers: +// - name: "version" +// value "v1" +// +// ``` +type HTTPRouteMatch struct { + // Path specifies a HTTP request path matcher. If this field is not + // specified, a default prefix match on the "/" path is provided. + // + // +optional + // +kubebuilder:default={type: "PathPrefix", value: "/"} + Path *HTTPPathMatch `json:"path,omitempty"` + + // 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. + // + // +listType=map + // +listMapKey=name + // +optional + // +kubebuilder:validation:MaxItems=16 + Headers []HTTPHeaderMatch `json:"headers,omitempty"` + + // 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. + // + // Support: Extended + // + // +listType=map + // +listMapKey=name + // +optional + // +kubebuilder:validation:MaxItems=16 + QueryParams []HTTPQueryParamMatch `json:"queryParams,omitempty"` + + // Method specifies HTTP method matcher. + // When specified, this route will be matched only if the request has the + // specified method. + // + // Support: Extended + // + // +optional + Method *HTTPMethod `json:"method,omitempty"` +} + +// 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. +// +// +kubebuilder:validation:XValidation:message="filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier",rule="!(has(self.requestHeaderModifier) && self.type != 'RequestHeaderModifier')" +// +kubebuilder:validation:XValidation:message="filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type",rule="!(!has(self.requestHeaderModifier) && self.type == 'RequestHeaderModifier')" +// +kubebuilder:validation:XValidation:message="filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier",rule="!(has(self.responseHeaderModifier) && self.type != 'ResponseHeaderModifier')" +// +kubebuilder:validation:XValidation:message="filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type",rule="!(!has(self.responseHeaderModifier) && self.type == 'ResponseHeaderModifier')" +// +kubebuilder:validation:XValidation:message="filter.requestMirror must be nil if the filter.type is not RequestMirror",rule="!(has(self.requestMirror) && self.type != 'RequestMirror')" +// +kubebuilder:validation:XValidation:message="filter.requestMirror must be specified for RequestMirror filter.type",rule="!(!has(self.requestMirror) && self.type == 'RequestMirror')" +// +kubebuilder:validation:XValidation:message="filter.requestRedirect must be nil if the filter.type is not RequestRedirect",rule="!(has(self.requestRedirect) && self.type != 'RequestRedirect')" +// +kubebuilder:validation:XValidation:message="filter.requestRedirect must be specified for RequestRedirect filter.type",rule="!(!has(self.requestRedirect) && self.type == 'RequestRedirect')" +// +kubebuilder:validation:XValidation:message="filter.urlRewrite must be nil if the filter.type is not URLRewrite",rule="!(has(self.urlRewrite) && self.type != 'URLRewrite')" +// +kubebuilder:validation:XValidation:message="filter.urlRewrite must be specified for URLRewrite filter.type",rule="!(!has(self.urlRewrite) && self.type == 'URLRewrite')" +// +kubebuilder:validation:XValidation:message="filter.extensionRef must be nil if the filter.type is not ExtensionRef",rule="!(has(self.extensionRef) && self.type != 'ExtensionRef')" +// +kubebuilder:validation:XValidation:message="filter.extensionRef must be specified for ExtensionRef filter.type",rule="!(!has(self.extensionRef) && self.type == 'ExtensionRef')" +type HTTPRouteFilter struct { + // Type identifies the type of filter to apply. As with other API fields, + // types are classified into three conformance levels: + // + // - Core: Filter types and their corresponding configuration defined by + // "Support: Core" in this package, e.g. "RequestHeaderModifier". All + // implementations must support core filters. + // + // - Extended: Filter types and their corresponding configuration defined by + // "Support: Extended" in this package, e.g. "RequestMirror". Implementers + // are encouraged to support extended filters. + // + // - Implementation-specific: Filters that are defined and supported by + // specific vendors. + // In the future, filters showing convergence in behavior across multiple + // implementations will be considered for inclusion in extended or core + // conformance levels. Filter-specific configuration for such filters + // is specified using the ExtensionRef field. `Type` should be set to + // "ExtensionRef" for custom filters. + // + // Implementers are encouraged to define custom implementation types to + // extend the core API with implementation-specific behavior. + // + // If a reference to a custom filter type cannot be resolved, the filter + // MUST NOT be skipped. Instead, requests that would have been processed by + // that filter MUST receive a HTTP error response. + // + // Note that values may be added to this enum, implementations + // must ensure that unknown values will not cause a crash. + // + // Unknown values here must result in the implementation setting the + // Accepted Condition for the Route to `status: False`, with a + // Reason of `UnsupportedValue`. + // + // +unionDiscriminator + // +kubebuilder:validation:Enum=RequestHeaderModifier;ResponseHeaderModifier;RequestMirror;RequestRedirect;URLRewrite;ExtensionRef + Type HTTPRouteFilterType `json:"type"` + + // RequestHeaderModifier defines a schema for a filter that modifies request + // headers. + // + // Support: Core + // + // +optional + RequestHeaderModifier *HTTPHeaderFilter `json:"requestHeaderModifier,omitempty"` + + // ResponseHeaderModifier defines a schema for a filter that modifies response + // headers. + // + // Support: Extended + // + // +optional + ResponseHeaderModifier *HTTPHeaderFilter `json:"responseHeaderModifier,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. + // + // This filter can be used multiple times within the same rule. Note that + // not all implementations will be able to support mirroring to multiple + // backends. + // + // Support: Extended + // + // +optional + RequestMirror *HTTPRequestMirrorFilter `json:"requestMirror,omitempty"` + + // RequestRedirect defines a schema for a filter that responds to the + // request with an HTTP redirection. + // + // Support: Core + // + // +optional + RequestRedirect *HTTPRequestRedirectFilter `json:"requestRedirect,omitempty"` + + // URLRewrite defines a schema for a filter that modifies a request during forwarding. + // + // Support: Extended + // + // +optional + URLRewrite *HTTPURLRewriteFilter `json:"urlRewrite,omitempty"` + + // ExtensionRef is an optional, implementation-specific extension to the + // "filter" behavior. For example, resource "myroutefilter" in group + // "networking.example.net"). ExtensionRef MUST NOT be used for core and + // extended filters. + // + // This filter can be used multiple times within the same rule. + // + // Support: Implementation-specific + // + // +optional + ExtensionRef *LocalObjectReference `json:"extensionRef,omitempty"` +} + +// HTTPRouteFilterType identifies a type of HTTPRoute filter. +type HTTPRouteFilterType string + +const ( + // HTTPRouteFilterRequestHeaderModifier can be used to add or remove an HTTP + // header from an HTTP request before it is sent to the upstream target. + // + // Support in HTTPRouteRule: Core + // + // Support in HTTPBackendRef: Extended + HTTPRouteFilterRequestHeaderModifier HTTPRouteFilterType = "RequestHeaderModifier" + + // HTTPRouteFilterResponseHeaderModifier can be used to add or remove an HTTP + // header from an HTTP response before it is sent to the client. + // + // Support in HTTPRouteRule: Extended + // + // Support in HTTPBackendRef: Extended + HTTPRouteFilterResponseHeaderModifier HTTPRouteFilterType = "ResponseHeaderModifier" + + // HTTPRouteFilterRequestRedirect can be used to redirect a request to + // another location. This filter can also be used for HTTP to HTTPS + // redirects. This may not be used on the same Route rule or BackendRef as a + // URLRewrite filter. + // + // Support in HTTPRouteRule: Core + // + // Support in HTTPBackendRef: Extended + HTTPRouteFilterRequestRedirect HTTPRouteFilterType = "RequestRedirect" + + // HTTPRouteFilterURLRewrite can be used to modify a request during + // forwarding. At most one of these filters may be used on a Route rule. + // This may not be used on the same Route rule or BackendRef as a + // RequestRedirect filter. + // + // Support in HTTPRouteRule: Extended + // + // Support in HTTPBackendRef: Extended + HTTPRouteFilterURLRewrite HTTPRouteFilterType = "URLRewrite" + + // HTTPRouteFilterRequestMirror can be used to mirror HTTP requests to a + // different backend. The responses from this backend MUST be ignored by + // the Gateway. + // + // Support in HTTPRouteRule: Extended + // + // Support in HTTPBackendRef: Extended + HTTPRouteFilterRequestMirror HTTPRouteFilterType = "RequestMirror" + + // HTTPRouteFilterExtensionRef should be used for configuring custom + // HTTP filters. + // + // Support in HTTPRouteRule: Implementation-specific + // + // Support in HTTPBackendRef: Implementation-specific + HTTPRouteFilterExtensionRef HTTPRouteFilterType = "ExtensionRef" +) + +// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. +type HTTPHeader struct { + // Name is the name of the HTTP Header to be matched. Name matching MUST be + // case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + // + // If multiple entries specify equivalent header names, the first entry with + // an equivalent name MUST be considered for a match. Subsequent entries + // with an equivalent header name MUST be ignored. Due to the + // case-insensitivity of header names, "foo" and "Foo" are considered + // equivalent. + Name HTTPHeaderName `json:"name"` + + // Value is the value of HTTP Header to be matched. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=4096 + Value string `json:"value"` +} + +// HTTPHeaderFilter defines a filter that modifies the headers of an HTTP +// request or response. Only one action for a given header name is permitted. +// Filters specifying multiple actions of the same or different type for any one +// header name are invalid and will be rejected by the webhook if installed. +// Configuration to set or add multiple values for a header must use RFC 7230 +// header value formatting, separating each value with a comma. +type HTTPHeaderFilter struct { + // Set overwrites the request with the given header (name, value) + // before the action. + // + // Input: + // GET /foo HTTP/1.1 + // my-header: foo + // + // Config: + // set: + // - name: "my-header" + // value: "bar" + // + // Output: + // GET /foo HTTP/1.1 + // my-header: bar + // + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=16 + Set []HTTPHeader `json:"set,omitempty"` + + // Add adds the given header(s) (name, value) to the request + // before the action. It appends to any existing values associated + // with the header name. + // + // Input: + // GET /foo HTTP/1.1 + // my-header: foo + // + // Config: + // add: + // - name: "my-header" + // value: "bar,baz" + // + // Output: + // GET /foo HTTP/1.1 + // my-header: foo,bar,baz + // + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=16 + Add []HTTPHeader `json:"add,omitempty"` + + // Remove the given header(s) from the HTTP request before the action. The + // value of Remove is a list of HTTP header names. Note that the header + // names are case-insensitive (see + // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + // + // Input: + // GET /foo HTTP/1.1 + // my-header1: foo + // my-header2: bar + // my-header3: baz + // + // Config: + // remove: ["my-header1", "my-header3"] + // + // Output: + // GET /foo HTTP/1.1 + // my-header2: bar + // + // +optional + // +listType=set + // +kubebuilder:validation:MaxItems=16 + Remove []string `json:"remove,omitempty"` +} + +// HTTPPathModifierType defines the type of path redirect or rewrite. +type HTTPPathModifierType string + +const ( + // This type of modifier indicates that the full path will be replaced + // by the specified value. + FullPathHTTPPathModifier HTTPPathModifierType = "ReplaceFullPath" + + // This type of modifier indicates that any prefix path matches will be + // replaced by the substitution value. For example, a path with a prefix + // match of "/foo" and a ReplacePrefixMatch substitution of "/bar" will have + // the "/foo" prefix replaced with "/bar" in matching requests. + // + // Note that this matches the behavior of the PathPrefix match type. This + // matches full path elements. A path element refers to the list of labels + // in the path split by the `/` separator. When specified, a trailing `/` is + // ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + // match the prefix `/abc`, but the path `/abcd` would not. + PrefixMatchHTTPPathModifier HTTPPathModifierType = "ReplacePrefixMatch" +) + +// HTTPPathModifier defines configuration for path modifiers. +// +// +kubebuilder:validation:XValidation:message="replaceFullPath must be specified when type is set to 'ReplaceFullPath'",rule="self.type == 'ReplaceFullPath' ? has(self.replaceFullPath) : true" +// +kubebuilder:validation:XValidation:message="type must be 'ReplaceFullPath' when replaceFullPath is set",rule="has(self.replaceFullPath) ? self.type == 'ReplaceFullPath' : true" +// +kubebuilder:validation:XValidation:message="replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch'",rule="self.type == 'ReplacePrefixMatch' ? has(self.replacePrefixMatch) : true" +// +kubebuilder:validation:XValidation:message="type must be 'ReplacePrefixMatch' when replacePrefixMatch is set",rule="has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" +type HTTPPathModifier struct { + // Type defines the type of path modifier. Additional types may be + // added in a future release of the API. + // + // Note that values may be added to this enum, implementations + // must ensure that unknown values will not cause a crash. + // + // Unknown values here must result in the implementation setting the + // Accepted Condition for the Route to `status: False`, with a + // Reason of `UnsupportedValue`. + // + // +kubebuilder:validation:Enum=ReplaceFullPath;ReplacePrefixMatch + Type HTTPPathModifierType `json:"type"` + + // ReplaceFullPath specifies the value with which to replace the full path + // of a request during a rewrite or redirect. + // + // +kubebuilder:validation:MaxLength=1024 + // +optional + ReplaceFullPath *string `json:"replaceFullPath,omitempty"` + + // ReplacePrefixMatch specifies the value with which to replace the prefix + // match of a request during a rewrite or redirect. For example, a request + // to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + // of "/xyz" would be modified to "/xyz/bar". + // + // Note that this matches the behavior of the PathPrefix match type. This + // matches full path elements. A path element refers to the list of labels + // in the path split by the `/` separator. When specified, a trailing `/` is + // ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + // match the prefix `/abc`, but the path `/abcd` would not. + // + // ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + // Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + // the implementation setting the Accepted Condition for the Route to `status: False`. + // + // Request Path | Prefix Match | Replace Prefix | Modified Path + // -------------|--------------|----------------|---------- + // /foo/bar | /foo | /xyz | /xyz/bar + // /foo/bar | /foo | /xyz/ | /xyz/bar + // /foo/bar | /foo/ | /xyz | /xyz/bar + // /foo/bar | /foo/ | /xyz/ | /xyz/bar + // /foo | /foo | /xyz | /xyz + // /foo/ | /foo | /xyz | /xyz/ + // /foo/bar | /foo | | /bar + // /foo/ | /foo | | / + // /foo | /foo | | / + // /foo/ | /foo | / | / + // /foo | /foo | / | / + // + // +kubebuilder:validation:MaxLength=1024 + // +optional + ReplacePrefixMatch *string `json:"replacePrefixMatch,omitempty"` +} + +// HTTPRequestRedirect defines a filter that redirects a request. This filter +// MUST NOT be used on the same Route rule as a HTTPURLRewrite filter. +type HTTPRequestRedirectFilter struct { + // Scheme is the scheme to be used in the value of the `Location` header in + // the response. When empty, the scheme of the request is used. + // + // Scheme redirects can affect the port of the redirect, for more information, + // refer to the documentation for the port field of this filter. + // + // Note that values may be added to this enum, implementations + // must ensure that unknown values will not cause a crash. + // + // Unknown values here must result in the implementation setting the + // Accepted Condition for the Route to `status: False`, with a + // Reason of `UnsupportedValue`. + // + // Support: Extended + // + // +optional + // +kubebuilder:validation:Enum=http;https + Scheme *string `json:"scheme,omitempty"` + + // Hostname is the hostname to be used in the value of the `Location` + // header in the response. + // When empty, the hostname in the `Host` header of the request is used. + // + // Support: Core + // + // +optional + Hostname *PreciseHostname `json:"hostname,omitempty"` + + // Path defines parameters used to modify the path of the incoming request. + // The modified path is then used to construct the `Location` header. When + // empty, the request path is used as-is. + // + // Support: Extended + // + // +optional + Path *HTTPPathModifier `json:"path,omitempty"` + + // Port is the port to be used in the value of the `Location` + // header in the response. + // + // If no port is specified, the redirect port MUST be derived using the + // following rules: + // + // * If redirect scheme is not-empty, the redirect port MUST be the well-known + // port associated with the redirect scheme. Specifically "http" to port 80 + // and "https" to port 443. If the redirect scheme does not have a + // well-known port, the listener port of the Gateway SHOULD be used. + // * If redirect scheme is empty, the redirect port MUST be the Gateway + // Listener port. + // + // Implementations SHOULD NOT add the port number in the 'Location' + // header in the following cases: + // + // * A Location header that will use HTTP (whether that is determined via + // the Listener protocol or the Scheme field) _and_ use port 80. + // * A Location header that will use HTTPS (whether that is determined via + // the Listener protocol or the Scheme field) _and_ use port 443. + // + // Support: Extended + // + // +optional + Port *PortNumber `json:"port,omitempty"` + + // StatusCode is the HTTP status code to be used in response. + // + // Note that values may be added to this enum, implementations + // must ensure that unknown values will not cause a crash. + // + // Unknown values here must result in the implementation setting the + // Accepted Condition for the Route to `status: False`, with a + // Reason of `UnsupportedValue`. + // + // Support: Core + // + // +optional + // +kubebuilder:default=302 + // +kubebuilder:validation:Enum=301;302 + StatusCode *int `json:"statusCode,omitempty"` +} + +// HTTPURLRewriteFilter defines a filter that modifies a request during +// forwarding. At most one of these filters may be used on a Route rule. This +// MUST NOT be used on the same Route rule as a HTTPRequestRedirect filter. +// +// Support: Extended +type HTTPURLRewriteFilter struct { + // Hostname is the value to be used to replace the Host header value during + // forwarding. + // + // Support: Extended + // + // +optional + Hostname *PreciseHostname `json:"hostname,omitempty"` + + // Path defines a path rewrite. + // + // Support: Extended + // + // +optional + Path *HTTPPathModifier `json:"path,omitempty"` +} + +// HTTPRequestMirrorFilter defines configuration for the RequestMirror filter. +type HTTPRequestMirrorFilter struct { + // BackendRef references a resource where mirrored requests are sent. + // + // Mirrored requests must be sent only to a single destination endpoint + // within this BackendRef, irrespective of how many endpoints are present + // within this BackendRef. + // + // If the referent cannot be found, this BackendRef is invalid and must be + // dropped from the Gateway. The controller must ensure the "ResolvedRefs" + // condition on the Route status is set to `status: False` and not configure + // this backend in the underlying implementation. + // + // If there is a cross-namespace reference to an *existing* object + // that is not allowed by a ReferenceGrant, the controller must ensure the + // "ResolvedRefs" condition on the Route is set to `status: False`, + // with the "RefNotPermitted" reason and not configure this backend in the + // underlying implementation. + // + // In either error case, the Message of the `ResolvedRefs` Condition + // should be used to provide more detail about the problem. + // + // Support: Extended for Kubernetes Service + // + // Support: Implementation-specific for any other resource + BackendRef BackendObjectReference `json:"backendRef"` +} + +// HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. +// +// Note that when a namespace different than the local namespace is specified, a +// ReferenceGrant object is required in the referent namespace to allow that +// namespace's owner to accept the reference. See the ReferenceGrant +// documentation for details. +// +// +// +// When the BackendRef points to a Kubernetes Service, implementations SHOULD +// honor the appProtocol field if it is set for the target Service Port. +// +// Implementations supporting appProtocol SHOULD recognize the Kubernetes +// Standard Application Protocols defined in KEP-3726. +// +// If a Service appProtocol isn't specified, an implementation MAY infer the +// backend protocol through its own means. Implementations MAY infer the +// protocol from the Route type referring to the backend Service. +// +// If a Route is not able to send traffic to the backend using the specified +// protocol then the backend is considered invalid. Implementations MUST set the +// "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. +// +// +type HTTPBackendRef struct { + // BackendRef is a reference to a backend to forward matched requests to. + // + // A BackendRef can be invalid for the following reasons. In all cases, the + // implementation MUST ensure the `ResolvedRefs` Condition on the Route + // is set to `status: False`, with a Reason and Message that indicate + // what is the cause of the error. + // + // A BackendRef is invalid if: + // + // * It refers to an unknown or unsupported kind of resource. In this + // case, the Reason must be set to `InvalidKind` and Message of the + // Condition must explain which kind of resource is unknown or unsupported. + // + // * It refers to a resource that does not exist. In this case, the Reason must + // be set to `BackendNotFound` and the Message of the Condition must explain + // which resource does not exist. + // + // * It refers a resource in another namespace when the reference has not been + // explicitly allowed by a ReferenceGrant (or equivalent concept). In this + // case, the Reason must be set to `RefNotPermitted` and the Message of the + // Condition must explain which cross-namespace reference is not allowed. + // + // * It refers to a Kubernetes Service that has an incompatible appProtocol + // for the given Route type + // + // * The BackendTLSPolicy object is installed in the cluster, a BackendTLSPolicy + // is present that refers to the Service, and the implementation is unable + // to meet the requirement. At the time of writing, BackendTLSPolicy is + // experimental, but once it becomes standard, this will become a MUST + // requirement. + // + // Support: Core for Kubernetes Service + // + // Support: Implementation-specific for any other resource + // + // Support for weight: Core + // + // Support for Kubernetes Service appProtocol: Extended + // + // Support for BackendTLSPolicy: Experimental and ImplementationSpecific + // + // +optional + BackendRef `json:",inline"` + + // Filters defined at this level should be executed if and only if the + // request is being forwarded to the backend defined here. + // + // Support: Implementation-specific (For broader support of filters, use the + // Filters field in HTTPRouteRule.) + // + // +optional + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:validation:XValidation:message="May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both",rule="!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" + // +kubebuilder:validation:XValidation:message="May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both",rule="!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" + // +kubebuilder:validation:XValidation:message="RequestHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1" + // +kubebuilder:validation:XValidation:message="ResponseHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1" + // +kubebuilder:validation:XValidation:message="RequestRedirect filter cannot be repeated",rule="self.filter(f, f.type == 'RequestRedirect').size() <= 1" + // +kubebuilder:validation:XValidation:message="URLRewrite filter cannot be repeated",rule="self.filter(f, f.type == 'URLRewrite').size() <= 1" + Filters []HTTPRouteFilter `json:"filters,omitempty"` +} + +// HTTPRouteStatus defines the observed state of HTTPRoute. +type HTTPRouteStatus struct { + RouteStatus `json:",inline"` +} diff --git a/apis/v1/object_reference_types.go b/apis/v1/object_reference_types.go new file mode 100644 index 0000000000..c9a58b15f8 --- /dev/null +++ b/apis/v1/object_reference_types.go @@ -0,0 +1,147 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +// LocalObjectReference identifies an API object within the namespace of the +// referrer. +// 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. +// +// 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. +type LocalObjectReference struct { + // Group is the group of the referent. For example, "gateway.networking.k8s.io". + // When unspecified or empty string, core API group is inferred. + Group Group `json:"group"` + + // Kind is kind of the referent. For example "HTTPRoute" or "Service". + Kind Kind `json:"kind"` + + // Name is the name of the referent. + Name ObjectName `json:"name"` +} + +// SecretObjectReference identifies an API object including its namespace, +// defaulting to Secret. +// +// 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. +// +// 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. +type SecretObjectReference struct { + // Group is the group of the referent. For example, "gateway.networking.k8s.io". + // When unspecified or empty string, core API group is inferred. + // + // +optional + // +kubebuilder:default="" + Group *Group `json:"group"` + + // Kind is kind of the referent. For example "Secret". + // + // +optional + // +kubebuilder:default=Secret + Kind *Kind `json:"kind"` + + // Name is the name of the referent. + Name ObjectName `json:"name"` + + // Namespace is the namespace of the referenced object. When unspecified, the local + // namespace is inferred. + // + // Note that when a namespace different than the local namespace is specified, + // a ReferenceGrant object is required in the referent namespace to allow that + // namespace's owner to accept the reference. See the ReferenceGrant + // documentation for details. + // + // Support: Core + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` +} + +// BackendObjectReference defines how an ObjectReference that is +// specific to BackendRef. It includes a few additional fields and features +// than a regular ObjectReference. +// +// Note that when a namespace different than the local namespace is specified, a +// ReferenceGrant object is required in the referent namespace to allow that +// namespace's owner to accept the reference. See the ReferenceGrant +// documentation for details. +// +// 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. +// +// 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. +// +// +kubebuilder:validation:XValidation:message="Must have port for Service reference",rule="(size(self.group) == 0 && self.kind == 'Service') ? has(self.port) : true" +type BackendObjectReference struct { + // Group is the group of the referent. For example, "gateway.networking.k8s.io". + // When unspecified or empty string, core API group is inferred. + // + // +optional + // +kubebuilder:default="" + Group *Group `json:"group,omitempty"` + + // Kind is the Kubernetes resource kind of the referent. For example + // "Service". + // + // Defaults to "Service" when not specified. + // + // ExternalName services can refer to CNAME DNS records that may live + // outside of the cluster and as such are difficult to reason about in + // terms of conformance. They also may not be safe to forward to (see + // CVE-2021-25740 for more information). Implementations SHOULD NOT + // support ExternalName Services. + // + // Support: Core (Services with a type other than ExternalName) + // + // Support: Implementation-specific (Services with type ExternalName) + // + // +optional + // +kubebuilder:default=Service + Kind *Kind `json:"kind,omitempty"` + + // Name is the name of the referent. + Name ObjectName `json:"name"` + + // Namespace is the namespace of the backend. When unspecified, the local + // namespace is inferred. + // + // Note that when a namespace different than the local namespace is specified, + // a ReferenceGrant object is required in the referent namespace to allow that + // namespace's owner to accept the reference. See the ReferenceGrant + // documentation for details. + // + // Support: Core + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` + + // Port specifies the destination port number to use for this resource. + // Port is required when the referent is a Kubernetes Service. In this + // case, the port number is the service port number, not the target port. + // For other resources, destination port might be derived from the referent + // resource or this field. + // + // +optional + Port *PortNumber `json:"port,omitempty"` +} diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go new file mode 100644 index 0000000000..21de37b5d2 --- /dev/null +++ b/apis/v1/shared_types.go @@ -0,0 +1,738 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ParentReference identifies an API object (usually a Gateway) that can be considered +// a parent of this resource (usually a route). There are two kinds of parent resources +// with "Core" support: +// +// * Gateway (Gateway conformance profile) +// * Service (Mesh conformance profile, experimental, ClusterIP Services only) +// +// This API may be extended in the future to support additional kinds of parent +// resources. +// +// 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. +type ParentReference struct { + // Group is the group of the referent. + // When unspecified, "gateway.networking.k8s.io" is inferred. + // To set the core API group (such as for a "Service" kind referent), + // Group must be explicitly set to "" (empty string). + // + // Support: Core + // + // +kubebuilder:default=gateway.networking.k8s.io + // +optional + Group *Group `json:"group,omitempty"` + + // Kind is kind of the referent. + // + // There are two kinds of parent resources with "Core" support: + // + // * Gateway (Gateway conformance profile) + // * Service (Mesh conformance profile, experimental, ClusterIP Services only) + // + // Support for other resources is Implementation-Specific. + // + // +kubebuilder:default=Gateway + // +optional + Kind *Kind `json:"kind,omitempty"` + + // Namespace is the namespace of the referent. When unspecified, this refers + // to the local namespace of the Route. + // + // Note that there are specific rules for ParentRefs which cross namespace + // boundaries. Cross-namespace references are only valid if they are explicitly + // allowed by something in the namespace they are referring to. For example: + // Gateway has the AllowedRoutes field, and ReferenceGrant provides a + // generic way to enable any other kind of cross-namespace reference. + // + // + // ParentRefs from a Route to a Service in the same namespace are "producer" + // routes, which apply default routing rules to inbound connections from + // any namespace to the Service. + // + // ParentRefs from a Route to a Service in a different namespace are + // "consumer" routes, and these routing rules are only applied to outbound + // connections originating from the same namespace as the Route, for which + // the intended destination of the connections are a Service targeted as a + // ParentRef of the Route. + // + // + // Support: Core + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` + + // Name is the name of the referent. + // + // Support: Core + Name ObjectName `json:"name"` + + // SectionName is the name of a section within the target resource. In the + // following resources, SectionName is interpreted as the following: + // + // * Gateway: Listener Name. When both Port (experimental) and SectionName + // are specified, the name and port of the selected listener must match + // both specified values. + // * Service: Port Name. When both Port (experimental) and SectionName + // are specified, the name and port of the selected listener must match + // both specified values. Note that attaching Routes to Services as Parents + // is part of experimental Mesh support and is not supported for any other + // purpose. + // + // Implementations MAY choose to support attaching Routes to other resources. + // If that is the case, they MUST clearly document how SectionName is + // interpreted. + // + // 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. + // + // Support: Core + // + // +optional + SectionName *SectionName `json:"sectionName,omitempty"` + + // Port is the network port this Route targets. It can be interpreted + // differently based on the type of parent resource. + // + // When the parent resource is a Gateway, this targets all listeners + // listening on the specified port that also support this kind of Route(and + // select this Route). It's not recommended to set `Port` unless the + // networking behaviors specified in a Route must apply to a specific port + // as opposed to a listener(s) whose port(s) may be changed. When both Port + // and SectionName are specified, the name and port of the selected listener + // must match both specified values. + // + // + // When the parent resource is a Service, this targets a specific port in the + // Service spec. When both Port (experimental) and SectionName are specified, + // the name and port of the selected port must match both specified values. + // + // + // Implementations MAY choose to support other parent resources. + // Implementations supporting other types of parent resources MUST clearly + // document how/if Port is interpreted. + // + // For the purpose of status, an attachment is considered successful as + // long as the parent resource accepts it partially. 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. + // + // Support: Extended + // + // +optional + // + Port *PortNumber `json:"port,omitempty"` +} + +// CommonRouteSpec defines the common attributes that all Routes MUST include +// within their spec. +type CommonRouteSpec struct { + // 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. For Services, that means the Service must either be in the same + // namespace for a "producer" route, or the mesh implementation must support + // and allow "consumer" routes for the referenced Service. ReferenceGrant is + // not applicable for governing ParentRefs to Services - it is not possible to + // create a "producer" route for a Service in a different namespace from the + // Route. + // + // There are two kinds of parent resources with "Core" support: + // + // * Gateway (Gateway conformance profile) + // + // * Service (Mesh conformance profile, experimental, ClusterIP Services only) + // + // This API may be extended in the future to support additional kinds of parent + // resources. + // + // ParentRefs must be _distinct_. This means either that: + // + // * They select different objects. If this is the case, then parentRef + // entries are distinct. In terms of fields, this means that the + // multi-part key defined by `group`, `kind`, `namespace`, and `name` must + // be unique across all parentRef entries in the Route. + // * They do not select different objects, but for each optional field used, + // each ParentRef that selects the same object must set the same set of + // optional fields to different values. If one ParentRef sets a + // combination of optional fields, all must set the same combination. + // + // Some examples: + // + // * If one ParentRef sets `sectionName`, all ParentRefs referencing the + // same object must also set `sectionName`. + // * If one ParentRef sets `port`, all ParentRefs referencing the same + // object must also set `port`. + // * If one ParentRef sets `sectionName` and `port`, all ParentRefs + // referencing the same object must also set `sectionName` and `port`. + // + // 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. + // + // Note that for ParentRefs that cross namespace boundaries, there are specific + // rules. Cross-namespace references are only valid if they are explicitly + // allowed by something in the namespace they are referring to. For example, + // Gateway has the AllowedRoutes field, and ReferenceGrant provides a + // generic way to enable other kinds of cross-namespace reference. + // + // + // ParentRefs from a Route to a Service in the same namespace are "producer" + // routes, which apply default routing rules to inbound connections from + // any namespace to the Service. + // + // ParentRefs from a Route to a Service in a different namespace are + // "consumer" routes, and these routing rules are only applied to outbound + // connections originating from the same namespace as the Route, for which + // the intended destination of the connections are a Service targeted as a + // ParentRef of the Route. + // + // + // +optional + // +kubebuilder:validation:MaxItems=32 + // + // + // + // + ParentRefs []ParentReference `json:"parentRefs,omitempty"` +} + +// PortNumber defines a network port. +// +// +kubebuilder:validation:Minimum=1 +// +kubebuilder:validation:Maximum=65535 +type PortNumber int32 + +// BackendRef defines how a Route should forward a request to a Kubernetes +// resource. +// +// Note that when a namespace different than the local namespace is specified, a +// ReferenceGrant object is required in the referent namespace to allow that +// namespace's owner to accept the reference. See the ReferenceGrant +// documentation for details. +// +// +// +// When the BackendRef points to a Kubernetes Service, implementations SHOULD +// honor the appProtocol field if it is set for the target Service Port. +// +// Implementations supporting appProtocol SHOULD recognize the Kubernetes +// Standard Application Protocols defined in KEP-3726. +// +// If a Service appProtocol isn't specified, an implementation MAY infer the +// backend protocol through its own means. Implementations MAY infer the +// protocol from the Route type referring to the backend Service. +// +// If a Route is not able to send traffic to the backend using the specified +// protocol then the backend is considered invalid. Implementations MUST set the +// "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. +// +// +// +// Note that when the BackendTLSPolicy object is enabled by the implementation, +// there are some extra rules about validity to consider here. See the fields +// where this struct is used for more information about the exact behavior. +type BackendRef struct { + // BackendObjectReference references a Kubernetes object. + BackendObjectReference `json:",inline"` + + // 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. + // + // 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. + // + // Support for this field varies based on the context where used. + // + // +optional + // +kubebuilder:default=1 + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=1000000 + Weight *int32 `json:"weight,omitempty"` +} + +// RouteConditionType is a type of condition for a route. +type RouteConditionType string + +// RouteConditionReason is a reason for a route condition. +type RouteConditionReason string + +const ( + // This condition indicates whether the route has been accepted or rejected + // by a Gateway, and why. + // + // Possible reasons for this condition to be True are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "NotAllowedByListeners" + // * "NoMatchingListenerHostname" + // * "NoMatchingParent" + // * "UnsupportedValue" + // + // Possible reasons for this condition to be Unknown are: + // + // * "Pending" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + RouteConditionAccepted RouteConditionType = "Accepted" + + // This reason is used with the "Accepted" condition when the Route has been + // accepted by the Gateway. + RouteReasonAccepted RouteConditionReason = "Accepted" + + // This reason is used with the "Accepted" condition when the route has not + // been accepted by a Gateway because the Gateway has no Listener whose + // allowedRoutes criteria permit the route + RouteReasonNotAllowedByListeners RouteConditionReason = "NotAllowedByListeners" + + // This reason is used with the "Accepted" condition when the Gateway has no + // compatible Listeners whose Hostname matches the route + RouteReasonNoMatchingListenerHostname RouteConditionReason = "NoMatchingListenerHostname" + + // This reason is used with the "Accepted" condition when there are + // no matching Parents. In the case of Gateways, this can occur when + // a Route ParentRef specifies a Port and/or SectionName that does not + // match any Listeners in the Gateway. + RouteReasonNoMatchingParent RouteConditionReason = "NoMatchingParent" + + // This reason is used with the "Accepted" condition when a value for an Enum + // is not recognized. + RouteReasonUnsupportedValue RouteConditionReason = "UnsupportedValue" + + // This reason is used with the "Accepted" when a controller has not yet + // reconciled the route. + RouteReasonPending RouteConditionReason = "Pending" + + // This reason is used with the "Accepted" condition when there + // are incompatible filters present on a route rule (for example if + // the URLRewrite and RequestRedirect are both present on an HTTPRoute). + RouteReasonIncompatibleFilters RouteConditionReason = "IncompatibleFilters" +) + +const ( + // This condition indicates whether the controller was able to resolve all + // the object references for the Route. + // + // Possible reasons for this condition to be True are: + // + // * "ResolvedRefs" + // + // Possible reasons for this condition to be False are: + // + // * "RefNotPermitted" + // * "InvalidKind" + // * "BackendNotFound" + // * "UnsupportedProtocol" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + RouteConditionResolvedRefs RouteConditionType = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the condition + // is true. + RouteReasonResolvedRefs RouteConditionReason = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when + // one of the Listener's Routes has a BackendRef to an object in + // another namespace, where the object in the other namespace does + // not have a ReferenceGrant explicitly allowing the reference. + RouteReasonRefNotPermitted RouteConditionReason = "RefNotPermitted" + + // This reason is used with the "ResolvedRefs" condition when + // one of the Route's rules has a reference to an unknown or unsupported + // Group and/or Kind. + RouteReasonInvalidKind RouteConditionReason = "InvalidKind" + + // This reason is used with the "ResolvedRefs" condition when one of the + // Route's rules has a reference to a resource that does not exist. + RouteReasonBackendNotFound RouteConditionReason = "BackendNotFound" + + // This reason is used with the "ResolvedRefs" condition when one of the + // Route's rules has a reference to a resource with an app protocol that + // is not supported by this implementation. + RouteReasonUnsupportedProtocol RouteConditionReason = "UnsupportedProtocol" +) + +const ( + // This condition indicates that the Route contains a combination of both + // valid and invalid rules. + // + // When this happens, implementations MUST take one of the following + // approaches: + // + // 1) Drop Rule(s): With this approach, implementations will drop the + // invalid Route Rule(s) until they are fully valid again. The message + // for this condition MUST start with the prefix "Dropped Rule" and + // include information about which Rules have been dropped. In this + // state, the "Accepted" condition MUST be set to "True" with the latest + // generation of the resource. + // 2) Fall Back: With this approach, implementations will fall back to the + // last known good state of the entire Route. The message for this + // condition MUST start with the prefix "Fall Back" and include + // information about why the current Rule(s) are invalid. To represent + // this, the "Accepted" condition MUST be set to "True" with the + // generation of the last known good state of the resource. + // + // Reverting to the last known good state should only be done by + // implementations that have a means of restoring that state if/when they + // are restarted. + // + // This condition MUST NOT be set if a Route is fully valid, fully invalid, + // or not accepted. By extension, that means that this condition MUST only + // be set when it is "True". + // + // Possible reasons for this condition to be True are: + // + // * "UnsupportedValue" + // + // Controllers may raise this condition with other reasons, but should + // prefer to use the reasons listed above to improve interoperability. + RouteConditionPartiallyInvalid RouteConditionType = "PartiallyInvalid" +) + +// RouteParentStatus describes the status of a route with respect to an +// associated Parent. +type RouteParentStatus struct { + // ParentRef corresponds with a ParentRef in the spec that this + // RouteParentStatus struct describes the status of. + ParentRef ParentReference `json:"parentRef"` + + // 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). + // + // Controllers MUST populate this field when writing status. Controllers should ensure that + // entries to status populated with their ControllerName are cleaned up when they are no + // longer necessary. + 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 + // status conditions and listener status. + // + // 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. + // + // 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 "Accepted" condition may not be set + // due to lack of controller visibility, that includes when: + // + // * 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 controller does not have access to. + // + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// RouteStatus defines the common attributes that all Routes MUST include within +// their status. +type RouteStatus struct { + // 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. + // + // 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. + // + // +kubebuilder:validation:MaxItems=32 + Parents []RouteParentStatus `json:"parents"` +} + +// 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. 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 +// domain name prefixed with a single wildcard label (e.g. `*.example.com`). +// +// 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. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +type Hostname string + +// PreciseHostname is the fully qualified domain name of a network host. This +// matches the RFC 1123 definition of a hostname with 1 notable exception that +// numeric IP addresses are not allowed. +// +// 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. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +type PreciseHostname string + +// Group refers to a Kubernetes Group. It must either be an empty string or a +// RFC 1123 subdomain. +// +// This validation is based off of the corresponding Kubernetes validation: +// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 +// +// Valid values include: +// +// * "" - empty string implies core Kubernetes API group +// * "gateway.networking.k8s.io" +// * "foo.example.com" +// +// Invalid values include: +// +// * "example.com/bar" - "/" is an invalid character +// +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +type Group string + +// Kind refers to a Kubernetes Kind. +// +// Valid values include: +// +// * "Service" +// * "HTTPRoute" +// +// Invalid values include: +// +// * "invalid/kind" - "/" is an invalid character +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=63 +// +kubebuilder:validation:Pattern=`^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` +type Kind string + +// ObjectName refers to the name of a Kubernetes object. +// Object names can have a variety of forms, including RFC1123 subdomains, +// RFC 1123 labels, or RFC 1035 labels. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +type ObjectName string + +// Namespace refers to a Kubernetes namespace. It must be a RFC 1123 label. +// +// This validation is based off of the corresponding Kubernetes validation: +// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L187 +// +// This is used for Namespace name validation here: +// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/api/validation/generic.go#L63 +// +// Valid values include: +// +// * "example" +// +// Invalid values include: +// +// * "example.com" - "." is an invalid character +// +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=63 +type Namespace string + +// 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 +// +// Valid values include: +// +// * "example.com" +// * "foo.example.com" +// +// Invalid values include: +// +// * "example.com/bar" - "/" is an invalid character +// +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +type SectionName string + +// GatewayController is the name of a Gateway API controller. It must be a +// domain prefixed path. +// +// Valid values include: +// +// * "example.com/bar" +// +// Invalid values include: +// +// * "example.com" - must include path +// * "foo.example.com" - must include path +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` +type GatewayController string + +// AnnotationKey is the key of an annotation in Gateway API. This is used for +// validation of maps such as TLS options. This matches the Kubernetes +// "qualified name" validation that is used for annotations and other common +// values. +// +// Valid values include: +// +// * example +// * example.com +// * example.com/path +// * example.com/path.html +// +// Invalid values include: +// +// * example~ - "~" is an invalid character +// * example.com. - can not start or end with "." +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]/?)*$` +type AnnotationKey string + +// 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. +// +// +kubebuilder:validation:MinLength=0 +// +kubebuilder:validation:MaxLength=4096 +type AnnotationValue string + +// AddressType defines how a network address is represented as a text string. +// This may take two possible forms: +// +// * A predefined CamelCase string identifier (currently limited to `IPAddress` or `Hostname`) +// * A domain-prefixed string identifier (like `acme.io/CustomAddressType`) +// +// Values `IPAddress` and `Hostname` have Extended support. +// +// The `NamedAddress` value has been deprecated in favor of implementation +// specific domain-prefixed strings. +// +// All other values, including domain-prefixed values have Implementation-specific support, +// which are used in implementation-specific behaviors. Support for additional +// predefined CamelCase identifiers may be added in future releases. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` +type AddressType string + +// HeaderName is the name of a header or query parameter. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=256 +// +kubebuilder:validation:Pattern=`^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$` +// +k8s:deepcopy-gen=false +type HeaderName string + +// Duration is a string value representing a duration in time. The format is as specified +// in GEP-2257, a strict subset of the syntax parsed by Golang time.ParseDuration. +// +// +kubebuilder:validation:Pattern=`^([0-9]{1,5}(h|m|s|ms)){1,4}$` +type Duration string + +const ( + // A textual representation of a numeric IP address. IPv4 + // addresses must be in dotted-decimal form. IPv6 addresses + // must be in a standard IPv6 text representation + // (see [RFC 5952](https://tools.ietf.org/html/rfc5952)). + // + // This type is intended for specific addresses. Address ranges are not + // supported (e.g. you can not use a CIDR range like 127.0.0.0/24 as an + // IPAddress). + // + // Support: Extended + IPAddressType AddressType = "IPAddress" + + // A Hostname represents a DNS based ingress point. This is similar to the + // corresponding hostname field in Kubernetes load balancer status. For + // example, this concept may be used for cloud load balancers where a DNS + // name is used to expose a load balancer. + // + // Support: Extended + HostnameAddressType AddressType = "Hostname" + + // A NamedAddress provides a way to reference a specific IP address by name. + // For example, this may be a name or other unique identifier that refers + // to a resource on a cloud provider such as a static IP. + // + // The `NamedAddress` type has been deprecated in favor of implementation + // specific domain-prefixed strings. + // + // Support: Implementation-specific + NamedAddressType AddressType = "NamedAddress" +) diff --git a/apis/v1/util/validation/gatewayclass.go b/apis/v1/util/validation/gatewayclass.go new file mode 100644 index 0000000000..d9b2654db9 --- /dev/null +++ b/apis/v1/util/validation/gatewayclass.go @@ -0,0 +1,34 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "regexp" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +var controllerNameRegex = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$`) + +// IsControllerNameValid checks that the provided controllerName complies with the expected +// format. It must be a non-empty domain prefixed path. +func IsControllerNameValid(controllerName gatewayv1.GatewayController) bool { + if controllerName == "" { + return false + } + return controllerNameRegex.Match([]byte(controllerName)) +} diff --git a/apis/v1/util/validation/gatewayclass_test.go b/apis/v1/util/validation/gatewayclass_test.go new file mode 100644 index 0000000000..7b49973bc2 --- /dev/null +++ b/apis/v1/util/validation/gatewayclass_test.go @@ -0,0 +1,68 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation_test + +import ( + "testing" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" + validationtutils "sigs.k8s.io/gateway-api/apis/v1beta1/util/validation" +) + +func TestIsControllerNameValid(t *testing.T) { + testCases := []struct { + name string + controllerName gatewayv1.GatewayController + isvalid bool + }{ + { + name: "empty controller name", + controllerName: "", + isvalid: false, + }, + { + name: "invalid controller name 1", + controllerName: "example.com", + isvalid: false, + }, + { + name: "invalid controller name 2", + controllerName: "example*com/bar", + isvalid: false, + }, + { + name: "invalid controller name 3", + controllerName: "example/@bar", + isvalid: false, + }, + { + name: "valid controller name", + controllerName: "example.com/bar", + isvalid: true, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + isValid := validationtutils.IsControllerNameValid(tc.controllerName) + if isValid != tc.isvalid { + t.Errorf("Expected validity %t, got %t", tc.isvalid, isValid) + } + }) + } +} diff --git a/apis/v1/validation/common.go b/apis/v1/validation/common.go new file mode 100644 index 0000000000..614f46b33d --- /dev/null +++ b/apis/v1/validation/common.go @@ -0,0 +1,86 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/util/validation/field" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// ValidateParentRefs validates ParentRefs SectionName must be set and unique +// when ParentRefs includes 2 or more references to the same parent +func ValidateParentRefs(parentRefs []gatewayv1.ParentReference, path *field.Path) field.ErrorList { + var errs field.ErrorList + if len(parentRefs) <= 1 { + return nil + } + type sameKindParentRefs struct { + name gatewayv1.ObjectName + namespace gatewayv1.Namespace + kind gatewayv1.Kind + } + type parentQualifier struct { + section gatewayv1.SectionName + port gatewayv1.PortNumber + } + parentRefsSectionMap := make(map[sameKindParentRefs]sets.Set[parentQualifier]) + for i, p := range parentRefs { + targetParentRefs := sameKindParentRefs{name: p.Name, namespace: gatewayv1.Namespace(""), kind: gatewayv1.Kind("")} + pq := parentQualifier{} + if p.Namespace != nil { + targetParentRefs.namespace = *p.Namespace + } + if p.Kind != nil { + targetParentRefs.kind = *p.Kind + } + if p.SectionName != nil { + pq.section = *p.SectionName + } + if p.Port != nil { + pq.port = *p.Port + } + if s, ok := parentRefsSectionMap[targetParentRefs]; ok { + if s.UnsortedList()[0] == (parentQualifier{}) || pq == (parentQualifier{}) { + errs = append(errs, field.Required(path.Child("parentRefs"), "sectionNames or ports must be specified when more than one parentRef refers to the same parent")) + return errs + } + if s.Has(pq) { + fieldPath := path.Index(i).Child("parentRefs") + var val any + if len(pq.section) > 0 { + fieldPath = fieldPath.Child("sectionName") + val = pq.section + } else { + fieldPath = fieldPath.Child("port") + val = pq.port + } + errs = append(errs, field.Invalid(fieldPath, val, "must be unique when ParentRefs includes 2 or more references to the same parent")) + return errs + } + parentRefsSectionMap[targetParentRefs].Insert(pq) + } else { + parentRefsSectionMap[targetParentRefs] = sets.New(pq) + } + } + return errs +} + +func ptrTo[T any](a T) *T { + return &a +} diff --git a/apis/v1/validation/common_test.go b/apis/v1/validation/common_test.go new file mode 100644 index 0000000000..41dd40aa31 --- /dev/null +++ b/apis/v1/validation/common_test.go @@ -0,0 +1,290 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "strings" + "testing" + + "k8s.io/apimachinery/pkg/util/validation/field" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +var path = field.Path{} + +func TestValidateParentRefs(t *testing.T) { + namespace := gatewayv1.Namespace("example-namespace") + kind := gatewayv1.Kind("Gateway") + sectionA := gatewayv1.SectionName("Section A") + sectionB := gatewayv1.SectionName("Section B") + sectionC := gatewayv1.SectionName("Section C") + + tests := []struct { + name string + parentRefs []gatewayv1.ParentReference + err string + }{{ + name: "valid ParentRefs includes 1 reference", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + Namespace: &namespace, + Kind: &kind, + SectionName: §ionA, + }, + }, + err: "", + }, { + name: "valid ParentRefs includes 2 references", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + Namespace: &namespace, + Kind: &kind, + SectionName: §ionA, + }, + { + Name: "example", + Namespace: &namespace, + Kind: &kind, + SectionName: §ionB, + }, + }, + err: "", + }, { + name: "valid ParentRefs when different references have the same section name", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example A", + Namespace: &namespace, + Kind: &kind, + SectionName: §ionA, + }, + { + Name: "example B", + Namespace: &namespace, + Kind: &kind, + SectionName: §ionA, + }, + }, + err: "", + }, { + name: "valid ParentRefs includes more references to the same parent", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + Namespace: &namespace, + Kind: &kind, + SectionName: §ionA, + }, + { + Name: "example", + Namespace: &namespace, + Kind: &kind, + SectionName: §ionB, + }, + { + Name: "example", + Namespace: &namespace, + Kind: &kind, + SectionName: §ionC, + }, + }, + err: "", + }, { + name: "invalid ParentRefs due to the same section names to the same parentRefs", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + Namespace: &namespace, + Kind: &kind, + SectionName: §ionA, + }, + { + Name: "example", + Namespace: &namespace, + Kind: &kind, + SectionName: §ionA, + }, + }, + err: "must be unique when ParentRefs", + }, { + name: "invalid ParentRefs due to section names not set to the same ParentRefs", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + }, + { + Name: "example", + }, + }, + err: "sectionNames or ports must be specified", + }, { + name: "invalid ParentRefs due to more same section names to the same ParentRefs", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + Namespace: &namespace, + SectionName: §ionA, + }, + { + Name: "example", + Namespace: &namespace, + SectionName: nil, + }, + { + Name: "example", + Namespace: &namespace, + SectionName: §ionB, + }, + { + Name: "example", + Namespace: &namespace, + SectionName: §ionA, + }, + }, + err: "sectionNames or ports must be specified", + }, { + name: "invalid ParentRefs when one ParentRef section name not set to the same ParentRefs", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + Namespace: &namespace, + SectionName: nil, + }, + { + Name: "example", + Namespace: &namespace, + SectionName: §ionA, + }, + }, + err: "sectionNames or ports must be specified", + }, { + name: "invalid ParentRefs when next ParentRef section name not set to the same ParentRefs", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + Namespace: &namespace, + SectionName: §ionA, + }, + { + Name: "example", + Namespace: &namespace, + SectionName: nil, + }, + }, + err: "sectionNames or ports must be specified", + }, { + name: "valid ParentRefs with multiple port references to the same parent", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + Namespace: &namespace, + Port: ptrTo(gatewayv1.PortNumber(80)), + }, + { + Name: "example", + Namespace: &namespace, + Port: ptrTo(gatewayv1.PortNumber(81)), + }, + }, + err: "", + }, { + name: "valid ParentRefs with multiple mixed references to the same parent", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + Namespace: &namespace, + Port: ptrTo(gatewayv1.PortNumber(80)), + }, + { + Name: "example", + Namespace: &namespace, + SectionName: §ionA, + }, + }, + err: "", + }, { + name: "invalid ParentRefs due to same port references to the same parent", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + Namespace: &namespace, + Port: ptrTo(gatewayv1.PortNumber(80)), + }, + { + Name: "example", + Namespace: &namespace, + Port: ptrTo(gatewayv1.PortNumber(80)), + }, + }, + err: "port: Invalid value: 80: must be unique when ParentRefs", + }, { + name: "invalid ParentRefs due to mixed port references to the same parent", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + Namespace: &namespace, + Port: ptrTo(gatewayv1.PortNumber(80)), + }, + { + Name: "example", + Namespace: &namespace, + Port: nil, + }, + }, + err: "Required value: sectionNames or ports must be specified", + }, { + name: "valid ParentRefs with multiple same port references to different section of a parent", + parentRefs: []gatewayv1.ParentReference{ + { + Name: "example", + Namespace: &namespace, + Port: ptrTo(gatewayv1.PortNumber(80)), + SectionName: §ionA, + }, + { + Name: "example", + Namespace: &namespace, + Port: ptrTo(gatewayv1.PortNumber(80)), + SectionName: §ionB, + }, + }, + err: "", + }} + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + spec := gatewayv1.CommonRouteSpec{ + ParentRefs: tc.parentRefs, + } + errs := ValidateParentRefs(spec.ParentRefs, path.Child("spec")) + if tc.err == "" { + if len(errs) != 0 { + t.Errorf("got %d errors, want none: %s", len(errs), errs) + } + } else { + if errs == nil { + t.Errorf("got no errors, want %q", tc.err) + } else if !strings.Contains(errs.ToAggregate().Error(), tc.err) { + t.Errorf("got %d errors, want %q: %s", len(errs), tc.err, errs) + } + } + }) + } +} diff --git a/apis/v1/validation/doc.go b/apis/v1/validation/doc.go new file mode 100644 index 0000000000..b874e70649 --- /dev/null +++ b/apis/v1/validation/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package validation has functions for validating the correctness of api +// objects and explaining what's wrong with them when they're not valid. +package validation // import "sigs.k8s.io/gateway-api/apis/v1/validation" diff --git a/apis/v1/validation/gateway.go b/apis/v1/validation/gateway.go new file mode 100644 index 0000000000..a2aa6afca5 --- /dev/null +++ b/apis/v1/validation/gateway.go @@ -0,0 +1,196 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "fmt" + "net/netip" + "regexp" + + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/util/validation/field" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +var ( + // set of protocols for which we need to validate that hostname is empty + protocolsHostnameInvalid = map[gatewayv1.ProtocolType]struct{}{ + gatewayv1.TCPProtocolType: {}, + gatewayv1.UDPProtocolType: {}, + } + // set of protocols for which TLSConfig shall not be present + protocolsTLSInvalid = map[gatewayv1.ProtocolType]struct{}{ + gatewayv1.HTTPProtocolType: {}, + gatewayv1.UDPProtocolType: {}, + gatewayv1.TCPProtocolType: {}, + } + // set of protocols for which TLSConfig must be set + protocolsTLSRequired = map[gatewayv1.ProtocolType]struct{}{ + gatewayv1.HTTPSProtocolType: {}, + gatewayv1.TLSProtocolType: {}, + } + + validHostnameAddress = `^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` + validHostnameRegexp = regexp.MustCompile(validHostnameAddress) +) + +// ValidateGateway validates gw according to the Gateway API specification. +// For additional details of the Gateway spec, refer to: +// +// https://gateway-api.sigs.k8s.io/v1beta1/references/spec/#gateway.networking.k8s.io/v1beta1.Gateway +// +// Validation that is not possible with CRD annotations may be added here in the future. +// See https://github.com/kubernetes-sigs/gateway-api/issues/868 for more information. +func ValidateGateway(gw *gatewayv1.Gateway) field.ErrorList { + return ValidateGatewaySpec(&gw.Spec, field.NewPath("spec")) +} + +// ValidateGatewaySpec validates whether required fields of spec are set according to the +// Gateway API specification. +func ValidateGatewaySpec(spec *gatewayv1.GatewaySpec, path *field.Path) field.ErrorList { + var errs field.ErrorList + errs = append(errs, validateGatewayListeners(spec.Listeners, path.Child("listeners"))...) + errs = append(errs, validateGatewayAddresses(spec.Addresses, path.Child("addresses"))...) + return errs +} + +// validateGatewayListeners validates whether required fields of listeners are set according +// to the Gateway API specification. +func validateGatewayListeners(listeners []gatewayv1.Listener, path *field.Path) field.ErrorList { + var errs field.ErrorList + errs = append(errs, ValidateListenerTLSConfig(listeners, path)...) + errs = append(errs, validateListenerHostname(listeners, path)...) + errs = append(errs, ValidateTLSCertificateRefs(listeners, path)...) + errs = append(errs, ValidateListenerNames(listeners, path)...) + errs = append(errs, validateHostnameProtocolPort(listeners, path)...) + return errs +} + +// ValidateListenerTLSConfig validates TLS config must be set when protocol is HTTPS or TLS, +// and TLS config shall not be present when protocol is HTTP, TCP or UDP +func ValidateListenerTLSConfig(listeners []gatewayv1.Listener, path *field.Path) field.ErrorList { + var errs field.ErrorList + for i, l := range listeners { + if isProtocolInSubset(l.Protocol, protocolsTLSRequired) && l.TLS == nil { + errs = append(errs, field.Forbidden(path.Index(i).Child("tls"), fmt.Sprintf("must be set for protocol %v", l.Protocol))) + } + if isProtocolInSubset(l.Protocol, protocolsTLSInvalid) && l.TLS != nil { + errs = append(errs, field.Forbidden(path.Index(i).Child("tls"), fmt.Sprintf("should be empty for protocol %v", l.Protocol))) + } + } + return errs +} + +func isProtocolInSubset(protocol gatewayv1.ProtocolType, set map[gatewayv1.ProtocolType]struct{}) bool { + _, ok := set[protocol] + return ok +} + +// validateListenerHostname validates each listener hostname +// should be empty in case protocol is TCP or UDP +func validateListenerHostname(listeners []gatewayv1.Listener, path *field.Path) field.ErrorList { + var errs field.ErrorList + for i, h := range listeners { + if isProtocolInSubset(h.Protocol, protocolsHostnameInvalid) && h.Hostname != nil { + errs = append(errs, field.Forbidden(path.Index(i).Child("hostname"), fmt.Sprintf("should be empty for protocol %v", h.Protocol))) + } + } + return errs +} + +// ValidateTLSCertificateRefs validates the certificateRefs +// must be set and not empty when tls config is set and +// TLSModeType is terminate +func ValidateTLSCertificateRefs(listeners []gatewayv1.Listener, path *field.Path) field.ErrorList { + var errs field.ErrorList + for i, c := range listeners { + if isProtocolInSubset(c.Protocol, protocolsTLSRequired) && c.TLS != nil { + if *c.TLS.Mode == gatewayv1.TLSModeTerminate && len(c.TLS.CertificateRefs) == 0 { + errs = append(errs, field.Forbidden(path.Index(i).Child("tls").Child("certificateRefs"), "should be set and not empty when TLSModeType is Terminate")) + } + } + } + return errs +} + +// ValidateListenerNames validates the names of the listeners +// must be unique within the Gateway +func ValidateListenerNames(listeners []gatewayv1.Listener, path *field.Path) field.ErrorList { + var errs field.ErrorList + nameMap := make(map[gatewayv1.SectionName]struct{}, len(listeners)) + for i, c := range listeners { + if _, found := nameMap[c.Name]; found { + errs = append(errs, field.Duplicate(path.Index(i).Child("name"), "must be unique within the Gateway")) + } + nameMap[c.Name] = struct{}{} + } + return errs +} + +// validateHostnameProtocolPort validates that the combination of port, protocol, and hostname are +// unique for each listener. +func validateHostnameProtocolPort(listeners []gatewayv1.Listener, path *field.Path) field.ErrorList { + var errs field.ErrorList + hostnameProtocolPortSets := sets.Set[string]{} + for i, listener := range listeners { + hostname := new(gatewayv1.Hostname) + if listener.Hostname != nil { + hostname = listener.Hostname + } + protocol := listener.Protocol + port := listener.Port + hostnameProtocolPort := fmt.Sprintf("%s:%s:%d", *hostname, protocol, port) + if hostnameProtocolPortSets.Has(hostnameProtocolPort) { + errs = append(errs, field.Duplicate(path.Index(i), "combination of port, protocol, and hostname must be unique for each listener")) + } else { + hostnameProtocolPortSets.Insert(hostnameProtocolPort) + } + } + return errs +} + +// validateGatewayAddresses validates whether fields of addresses are set according +// to the Gateway API specification. +func validateGatewayAddresses(addresses []gatewayv1.GatewayAddress, path *field.Path) field.ErrorList { + var errs field.ErrorList + ipAddrSet, hostnameAddrSet := sets.Set[string]{}, sets.Set[string]{} + for i, address := range addresses { + if address.Type != nil { + if *address.Type == gatewayv1.IPAddressType { + if _, err := netip.ParseAddr(address.Value); err != nil { + errs = append(errs, field.Invalid(path.Index(i), address.Value, "invalid ip address")) + } + if ipAddrSet.Has(address.Value) { + errs = append(errs, field.Duplicate(path.Index(i), address.Value)) + } else { + ipAddrSet.Insert(address.Value) + } + } else if *address.Type == gatewayv1.HostnameAddressType { + if !validHostnameRegexp.MatchString(address.Value) { + errs = append(errs, field.Invalid(path.Index(i), address.Value, fmt.Sprintf("must only contain valid characters (matching %s)", validHostnameAddress))) + } + if hostnameAddrSet.Has(address.Value) { + errs = append(errs, field.Duplicate(path.Index(i), address.Value)) + } else { + hostnameAddrSet.Insert(address.Value) + } + } + } + } + return errs +} diff --git a/apis/v1/validation/gateway_test.go b/apis/v1/validation/gateway_test.go new file mode 100644 index 0000000000..8294485f89 --- /dev/null +++ b/apis/v1/validation/gateway_test.go @@ -0,0 +1,444 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "fmt" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/validation/field" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +func TestValidateGateway(t *testing.T) { + listeners := []gatewayv1.Listener{ + { + Hostname: nil, + }, + } + addresses := []gatewayv1.GatewayAddress{ + { + Type: nil, + }, + } + baseGateway := gatewayv1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: metav1.NamespaceDefault, + }, + Spec: gatewayv1.GatewaySpec{ + GatewayClassName: "foo", + Listeners: listeners, + Addresses: addresses, + }, + } + tlsConfig := gatewayv1.GatewayTLSConfig{} + + testCases := map[string]struct { + mutate func(gw *gatewayv1.Gateway) + expectErrs []field.Error + }{ + "tls config present with http protocol": { + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPProtocolType + gw.Spec.Listeners[0].TLS = &tlsConfig + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeForbidden, + Field: "spec.listeners[0].tls", + Detail: "should be empty for protocol HTTP", + BadValue: "", + }, + }, + }, + "tls config present with tcp protocol": { + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners[0].Protocol = gatewayv1.TCPProtocolType + gw.Spec.Listeners[0].TLS = &tlsConfig + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeForbidden, + Field: "spec.listeners[0].tls", + Detail: "should be empty for protocol TCP", + BadValue: "", + }, + }, + }, + "tls config not set with https protocol": { + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPSProtocolType + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeForbidden, + Field: "spec.listeners[0].tls", + Detail: "must be set for protocol HTTPS", + BadValue: "", + }, + }, + }, + "tls config not set with tls protocol": { + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners[0].Protocol = gatewayv1.TLSProtocolType + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeForbidden, + Field: "spec.listeners[0].tls", + Detail: "must be set for protocol TLS", + BadValue: "", + }, + }, + }, + "tls config not set with http protocol": { + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPProtocolType + }, + expectErrs: nil, + }, + "tls config not set with tcp protocol": { + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners[0].Protocol = gatewayv1.TCPProtocolType + }, + expectErrs: nil, + }, + "tls config not set with udp protocol": { + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners[0].Protocol = gatewayv1.UDPProtocolType + }, + expectErrs: nil, + }, + "hostname present with tcp protocol": { + mutate: func(gw *gatewayv1.Gateway) { + hostname := gatewayv1.Hostname("foo.bar.com") + gw.Spec.Listeners[0].Hostname = &hostname + gw.Spec.Listeners[0].Protocol = gatewayv1.TCPProtocolType + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeForbidden, + Field: "spec.listeners[0].hostname", + Detail: "should be empty for protocol TCP", + BadValue: "", + }, + }, + }, + "hostname present with udp protocol": { + mutate: func(gw *gatewayv1.Gateway) { + hostname := gatewayv1.Hostname("foo.bar.com") + gw.Spec.Listeners[0].Hostname = &hostname + gw.Spec.Listeners[0].Protocol = gatewayv1.UDPProtocolType + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeForbidden, + Field: "spec.listeners[0].hostname", + Detail: "should be empty for protocol UDP", + BadValue: "", + }, + }, + }, + "certificatedRefs not set with https protocol and TLS terminate mode": { + mutate: func(gw *gatewayv1.Gateway) { + hostname := gatewayv1.Hostname("foo.bar.com") + tlsMode := gatewayv1.TLSModeType("Terminate") + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPSProtocolType + gw.Spec.Listeners[0].Hostname = &hostname + gw.Spec.Listeners[0].TLS = &tlsConfig + gw.Spec.Listeners[0].TLS.Mode = &tlsMode + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeForbidden, + Field: "spec.listeners[0].tls.certificateRefs", + Detail: "should be set and not empty when TLSModeType is Terminate", + BadValue: "", + }, + }, + }, + "certificatedRefs not set with tls protocol and TLS terminate mode": { + mutate: func(gw *gatewayv1.Gateway) { + hostname := gatewayv1.Hostname("foo.bar.com") + tlsMode := gatewayv1.TLSModeType("Terminate") + gw.Spec.Listeners[0].Protocol = gatewayv1.TLSProtocolType + gw.Spec.Listeners[0].Hostname = &hostname + gw.Spec.Listeners[0].TLS = &tlsConfig + gw.Spec.Listeners[0].TLS.Mode = &tlsMode + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeForbidden, + Field: "spec.listeners[0].tls.certificateRefs", + Detail: "should be set and not empty when TLSModeType is Terminate", + BadValue: "", + }, + }, + }, + "names are not unique within the Gateway": { + mutate: func(gw *gatewayv1.Gateway) { + hostnameFoo := gatewayv1.Hostname("foo.com") + hostnameBar := gatewayv1.Hostname("bar.com") + gw.Spec.Listeners[0].Name = "foo" + gw.Spec.Listeners[0].Hostname = &hostnameFoo + gw.Spec.Listeners = append(gw.Spec.Listeners, + gatewayv1.Listener{ + Name: "foo", + Hostname: &hostnameBar, + }, + ) + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeDuplicate, + Field: "spec.listeners[1].name", + BadValue: "must be unique within the Gateway", + }, + }, + }, + "combination of port, protocol, and hostname are not unique for each listener": { + mutate: func(gw *gatewayv1.Gateway) { + hostnameFoo := gatewayv1.Hostname("foo.com") + gw.Spec.Listeners[0].Name = "foo" + gw.Spec.Listeners[0].Hostname = &hostnameFoo + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPProtocolType + gw.Spec.Listeners[0].Port = 80 + gw.Spec.Listeners = append(gw.Spec.Listeners, + gatewayv1.Listener{ + Name: "bar", + Hostname: &hostnameFoo, + Protocol: gatewayv1.HTTPProtocolType, + Port: 80, + }, + ) + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeDuplicate, + Field: "spec.listeners[1]", + BadValue: "combination of port, protocol, and hostname must be unique for each listener", + }, + }, + }, + "combination of port and protocol are not unique for each listener when hostnames not set": { + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners[0].Name = "foo" + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPProtocolType + gw.Spec.Listeners[0].Port = 80 + gw.Spec.Listeners = append(gw.Spec.Listeners, + gatewayv1.Listener{ + Name: "bar", + Protocol: gatewayv1.HTTPProtocolType, + Port: 80, + }, + ) + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeDuplicate, + Field: "spec.listeners[1]", + BadValue: "combination of port, protocol, and hostname must be unique for each listener", + }, + }, + }, + "port is unique when protocol and hostname are the same": { + mutate: func(gw *gatewayv1.Gateway) { + hostnameFoo := gatewayv1.Hostname("foo.com") + gw.Spec.Listeners[0].Name = "foo" + gw.Spec.Listeners[0].Hostname = &hostnameFoo + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPProtocolType + gw.Spec.Listeners[0].Port = 80 + gw.Spec.Listeners = append(gw.Spec.Listeners, + gatewayv1.Listener{ + Name: "bar", + Hostname: &hostnameFoo, + Protocol: gatewayv1.HTTPProtocolType, + Port: 8080, + }, + ) + }, + expectErrs: nil, + }, + "hostname is unique when protocol and port are the same": { + mutate: func(gw *gatewayv1.Gateway) { + hostnameFoo := gatewayv1.Hostname("foo.com") + hostnameBar := gatewayv1.Hostname("bar.com") + gw.Spec.Listeners[0].Name = "foo" + gw.Spec.Listeners[0].Hostname = &hostnameFoo + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPProtocolType + gw.Spec.Listeners[0].Port = 80 + gw.Spec.Listeners = append(gw.Spec.Listeners, + gatewayv1.Listener{ + Name: "bar", + Hostname: &hostnameBar, + Protocol: gatewayv1.HTTPProtocolType, + Port: 80, + }, + ) + }, + expectErrs: nil, + }, + "protocol is unique when port and hostname are the same": { + mutate: func(gw *gatewayv1.Gateway) { + hostnameFoo := gatewayv1.Hostname("foo.com") + tlsConfigFoo := tlsConfig + tlsModeFoo := gatewayv1.TLSModeType("Terminate") + tlsConfigFoo.Mode = &tlsModeFoo + tlsConfigFoo.CertificateRefs = []gatewayv1.SecretObjectReference{ + { + Name: "FooCertificateRefs", + }, + } + gw.Spec.Listeners[0].Name = "foo" + gw.Spec.Listeners[0].Hostname = &hostnameFoo + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPSProtocolType + gw.Spec.Listeners[0].Port = 8000 + gw.Spec.Listeners[0].TLS = &tlsConfigFoo + gw.Spec.Listeners = append(gw.Spec.Listeners, + gatewayv1.Listener{ + Name: "bar", + Hostname: &hostnameFoo, + Protocol: gatewayv1.TLSProtocolType, + Port: 8000, + TLS: &tlsConfigFoo, + }, + ) + }, + expectErrs: nil, + }, + "ip address and hostname in addresses are valid": { + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Addresses = []gatewayv1.GatewayAddress{ + { + Type: ptrTo(gatewayv1.IPAddressType), + Value: "1.2.3.4", + }, + { + Type: ptrTo(gatewayv1.IPAddressType), + Value: "1111:2222:3333:4444::", + }, + { + Type: ptrTo(gatewayv1.HostnameAddressType), + Value: "foo.bar", + }, + } + }, + expectErrs: nil, + }, + "ip address and hostname in addresses are invalid": { + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Addresses = []gatewayv1.GatewayAddress{ + { + Type: ptrTo(gatewayv1.IPAddressType), + Value: "1.2.3.4:8080", + }, + { + Type: ptrTo(gatewayv1.HostnameAddressType), + Value: "*foo/bar", + }, + { + Type: ptrTo(gatewayv1.HostnameAddressType), + Value: "12:34:56::", + }, + } + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeInvalid, + Field: "spec.addresses[0]", + Detail: "invalid ip address", + BadValue: "1.2.3.4:8080", + }, + { + Type: field.ErrorTypeInvalid, + Field: "spec.addresses[1]", + Detail: fmt.Sprintf("must only contain valid characters (matching %s)", validHostnameAddress), + BadValue: "*foo/bar", + }, + { + Type: field.ErrorTypeInvalid, + Field: "spec.addresses[2]", + Detail: fmt.Sprintf("must only contain valid characters (matching %s)", validHostnameAddress), + BadValue: "12:34:56::", + }, + }, + }, + "duplicate ip address or hostname": { + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Addresses = []gatewayv1.GatewayAddress{ + { + Type: ptrTo(gatewayv1.IPAddressType), + Value: "1.2.3.4", + }, + { + Type: ptrTo(gatewayv1.IPAddressType), + Value: "1.2.3.4", + }, + { + Type: ptrTo(gatewayv1.HostnameAddressType), + Value: "foo.bar", + }, + { + Type: ptrTo(gatewayv1.HostnameAddressType), + Value: "foo.bar", + }, + } + }, + expectErrs: []field.Error{ + { + Type: field.ErrorTypeDuplicate, + Field: "spec.addresses[1]", + BadValue: "1.2.3.4", + }, + { + Type: field.ErrorTypeDuplicate, + Field: "spec.addresses[3]", + BadValue: "foo.bar", + }, + }, + }, + } + + for name, tc := range testCases { + tc := tc + t.Run(name, func(t *testing.T) { + gw := baseGateway.DeepCopy() + tc.mutate(gw) + errs := ValidateGateway(gw) + if len(tc.expectErrs) != len(errs) { + t.Fatalf("Expected %d errors, got %d errors: %v", len(tc.expectErrs), len(errs), errs) + } + for i, err := range errs { + if err.Type != tc.expectErrs[i].Type { + t.Errorf("Expected error on type: %s, got: %s", tc.expectErrs[i].Type, err.Type) + } + if err.Field != tc.expectErrs[i].Field { + t.Errorf("Expected error on field: %s, got: %s", tc.expectErrs[i].Field, err.Field) + } + if err.Detail != tc.expectErrs[i].Detail { + t.Errorf("Expected error on detail: %s, got: %s", tc.expectErrs[i].Detail, err.Detail) + } + if err.BadValue != tc.expectErrs[i].BadValue { + t.Errorf("Expected error on bad value: %s, got: %s", tc.expectErrs[i].BadValue, err.BadValue) + } + } + }) + } +} diff --git a/apis/v1/validation/gatewayclass.go b/apis/v1/validation/gatewayclass.go new file mode 100644 index 0000000000..6c3762225e --- /dev/null +++ b/apis/v1/validation/gatewayclass.go @@ -0,0 +1,38 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "k8s.io/apimachinery/pkg/util/validation/field" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// ValidateGatewayClassUpdate validates an update to oldClass according to the +// Gateway API specification. For additional details of the GatewayClass spec, refer to: +// https://gateway-api.sigs.k8s.io/v1beta1/references/spec/#gateway.networking.k8s.io/v1beta1.GatewayClass +func ValidateGatewayClassUpdate(oldClass, newClass *gatewayv1.GatewayClass) field.ErrorList { + if oldClass == nil || newClass == nil { + return nil + } + var errs field.ErrorList + 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/v1/validation/gatewayclass_test.go b/apis/v1/validation/gatewayclass_test.go new file mode 100644 index 0000000000..f10028a990 --- /dev/null +++ b/apis/v1/validation/gatewayclass_test.go @@ -0,0 +1,98 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "reflect" + "testing" + + "k8s.io/apimachinery/pkg/util/validation/field" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +func TestValidateGatewayClassUpdate(t *testing.T) { + type args struct { + oldClass *gatewayv1.GatewayClass + newClass *gatewayv1.GatewayClass + } + tests := []struct { + name string + args args + want field.ErrorList + }{ + { + name: "changing parameters reference is allowed", + args: args{ + oldClass: &gatewayv1.GatewayClass{ + Spec: gatewayv1.GatewayClassSpec{ + ControllerName: "foo", + }, + }, + newClass: &gatewayv1.GatewayClass{ + Spec: gatewayv1.GatewayClassSpec{ + ControllerName: "foo", + ParametersRef: &gatewayv1.ParametersReference{ + Group: "example.com", + Kind: "GatewayClassConfig", + Name: "foo", + }, + }, + }, + }, + want: nil, + }, + { + name: "changing controller field results in an error", + args: args{ + oldClass: &gatewayv1.GatewayClass{ + Spec: gatewayv1.GatewayClassSpec{ + ControllerName: "example.com/gateway", + }, + }, + newClass: &gatewayv1.GatewayClass{ + Spec: gatewayv1.GatewayClassSpec{ + ControllerName: "example.org/gateway", + }, + }, + }, + want: field.ErrorList{ + { + Type: field.ErrorTypeInvalid, + Field: "spec.controllerName", + Detail: "cannot update an immutable field", + BadValue: gatewayv1.GatewayController("example.org/gateway"), + }, + }, + }, + { + name: "nil input result in no errors", + args: args{ + oldClass: nil, + newClass: nil, + }, + want: nil, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + if got := ValidateGatewayClassUpdate(tc.args.oldClass, tc.args.newClass); !reflect.DeepEqual(got, tc.want) { + t.Errorf("ValidateGatewayClassUpdate() = %v, want %v", got, tc.want) + } + }) + } +} diff --git a/apis/v1/validation/httproute.go b/apis/v1/validation/httproute.go new file mode 100644 index 0000000000..15ac859de0 --- /dev/null +++ b/apis/v1/validation/httproute.go @@ -0,0 +1,381 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "fmt" + "net/http" + "regexp" + "strings" + "time" + + "k8s.io/apimachinery/pkg/util/validation/field" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +var ( + // repeatableHTTPRouteFilters are filter types that are allowed to be + // repeated multiple times in a rule. + repeatableHTTPRouteFilters = []gatewayv1.HTTPRouteFilterType{ + gatewayv1.HTTPRouteFilterExtensionRef, + gatewayv1.HTTPRouteFilterRequestMirror, + } + + // Invalid path sequences and suffixes, primarily related to directory traversal + invalidPathSequences = []string{"//", "/./", "/../", "%2f", "%2F", "#"} + invalidPathSuffixes = []string{"/..", "/."} + + // All valid path characters per RFC-3986 + validPathCharacters = "^(?:[A-Za-z0-9\\/\\-._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$" +) + +// ValidateHTTPRoute validates HTTPRoute according to the Gateway API specification. +// For additional details of the HTTPRoute spec, refer to: +// https://gateway-api.sigs.k8s.io/v1beta1/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRoute +func ValidateHTTPRoute(route *gatewayv1.HTTPRoute) field.ErrorList { + return ValidateHTTPRouteSpec(&route.Spec, field.NewPath("spec")) +} + +// ValidateHTTPRouteSpec validates that required fields of spec are set according to the +// HTTPRoute specification. +func ValidateHTTPRouteSpec(spec *gatewayv1.HTTPRouteSpec, path *field.Path) field.ErrorList { + var errs field.ErrorList + for i, rule := range spec.Rules { + errs = append(errs, validateHTTPRouteFilters(rule.Filters, rule.Matches, path.Child("rules").Index(i))...) + errs = append(errs, validateRequestRedirectFiltersWithBackendRefs(rule, path.Child("rules").Index(i))...) + for j, backendRef := range rule.BackendRefs { + errs = append(errs, validateHTTPRouteFilters(backendRef.Filters, rule.Matches, path.Child("rules").Index(i).Child("backendRefs").Index(j))...) + } + for j, m := range rule.Matches { + matchPath := path.Child("rules").Index(i).Child("matches").Index(j) + + if m.Path != nil { + errs = append(errs, validateHTTPPathMatch(m.Path, matchPath.Child("path"))...) + } + if len(m.Headers) > 0 { + errs = append(errs, validateHTTPHeaderMatches(m.Headers, matchPath.Child("headers"))...) + } + if len(m.QueryParams) > 0 { + errs = append(errs, validateHTTPQueryParamMatches(m.QueryParams, matchPath.Child("queryParams"))...) + } + } + + if rule.Timeouts != nil { + errs = append(errs, validateHTTPRouteTimeouts(rule.Timeouts, path.Child("rules").Child("timeouts"))...) + } + } + errs = append(errs, validateHTTPRouteBackendServicePorts(spec.Rules, path.Child("rules"))...) + errs = append(errs, ValidateParentRefs(spec.ParentRefs, path.Child("spec"))...) + return errs +} + +// validateRequestRedirectFiltersWithBackendRefs validates that RequestRedirect filters are not used with backendRefs +func validateRequestRedirectFiltersWithBackendRefs(rule gatewayv1.HTTPRouteRule, path *field.Path) field.ErrorList { + var errs field.ErrorList + for _, filter := range rule.Filters { + if filter.RequestRedirect != nil && len(rule.BackendRefs) > 0 { + errs = append(errs, field.Invalid(path.Child("filters"), gatewayv1.HTTPRouteFilterRequestRedirect, "RequestRedirect filter is not allowed with backendRefs")) + } + } + return errs +} + +// validateHTTPRouteBackendServicePorts validates that v1.Service backends always have a port. +func validateHTTPRouteBackendServicePorts(rules []gatewayv1.HTTPRouteRule, path *field.Path) field.ErrorList { + var errs field.ErrorList + + for i, rule := range rules { + path = path.Index(i).Child("backendRefs") + for i, ref := range rule.BackendRefs { + if ref.BackendObjectReference.Group != nil && + *ref.BackendObjectReference.Group != "" { + continue + } + + if ref.BackendObjectReference.Kind != nil && + *ref.BackendObjectReference.Kind != "Service" { + continue + } + + if ref.BackendObjectReference.Port == nil { + errs = append(errs, field.Required(path.Index(i).Child("port"), "missing port for Service reference")) + } + } + } + + return errs +} + +// validateHTTPRouteFilters validates that a list of core and extended filters +// is used at most once and that the filter type matches its value +func validateHTTPRouteFilters(filters []gatewayv1.HTTPRouteFilter, matches []gatewayv1.HTTPRouteMatch, path *field.Path) field.ErrorList { + var errs field.ErrorList + counts := map[gatewayv1.HTTPRouteFilterType]int{} + + for i, filter := range filters { + counts[filter.Type]++ + if filter.RequestRedirect != nil && filter.RequestRedirect.Path != nil { + errs = append(errs, validateHTTPPathModifier(*filter.RequestRedirect.Path, matches, path.Index(i).Child("requestRedirect", "path"))...) + } + if filter.URLRewrite != nil && filter.URLRewrite.Path != nil { + errs = append(errs, validateHTTPPathModifier(*filter.URLRewrite.Path, matches, path.Index(i).Child("urlRewrite", "path"))...) + } + if filter.RequestHeaderModifier != nil { + errs = append(errs, validateHTTPHeaderModifier(*filter.RequestHeaderModifier, path.Index(i).Child("requestHeaderModifier"))...) + } + if filter.ResponseHeaderModifier != nil { + errs = append(errs, validateHTTPHeaderModifier(*filter.ResponseHeaderModifier, path.Index(i).Child("responseHeaderModifier"))...) + } + errs = append(errs, validateHTTPRouteFilterTypeMatchesValue(filter, path.Index(i))...) + } + + if counts[gatewayv1.HTTPRouteFilterRequestRedirect] > 0 && counts[gatewayv1.HTTPRouteFilterURLRewrite] > 0 { + errs = append(errs, field.Invalid(path.Child("filters"), gatewayv1.HTTPRouteFilterRequestRedirect, "may specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both")) + } + + // repeatableHTTPRouteFilters filters can be used more than once + for _, key := range repeatableHTTPRouteFilters { + delete(counts, key) + } + + for filterType, count := range counts { + if count > 1 { + errs = append(errs, field.Invalid(path.Child("filters"), filterType, "cannot be used multiple times in the same rule")) + } + } + return errs +} + +// webhook validation of HTTPPathMatch +func validateHTTPPathMatch(path *gatewayv1.HTTPPathMatch, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if path.Type == nil { + return append(allErrs, field.Required(fldPath.Child("type"), "must be specified")) + } + + if path.Value == nil { + return append(allErrs, field.Required(fldPath.Child("value"), "must be specified")) + } + + switch *path.Type { + case gatewayv1.PathMatchExact, gatewayv1.PathMatchPathPrefix: + if !strings.HasPrefix(*path.Value, "/") { + allErrs = append(allErrs, field.Invalid(fldPath.Child("value"), *path.Value, "must be an absolute path")) + } + if len(*path.Value) > 0 { + for _, invalidSeq := range invalidPathSequences { + if strings.Contains(*path.Value, invalidSeq) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("value"), *path.Value, fmt.Sprintf("must not contain %q", invalidSeq))) + } + } + + for _, invalidSuff := range invalidPathSuffixes { + if strings.HasSuffix(*path.Value, invalidSuff) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("value"), *path.Value, fmt.Sprintf("cannot end with '%s'", invalidSuff))) + } + } + } + + r, err := regexp.Compile(validPathCharacters) + if err != nil { + allErrs = append(allErrs, field.InternalError(fldPath.Child("value"), + fmt.Errorf("could not compile path matching regex: %w", err))) + } else if !r.MatchString(*path.Value) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("value"), *path.Value, + fmt.Sprintf("must only contain valid characters (matching %s)", validPathCharacters))) + } + + case gatewayv1.PathMatchRegularExpression: + default: + pathTypes := []string{string(gatewayv1.PathMatchExact), string(gatewayv1.PathMatchPathPrefix), string(gatewayv1.PathMatchRegularExpression)} + allErrs = append(allErrs, field.NotSupported(fldPath.Child("type"), *path.Type, pathTypes)) + } + return allErrs +} + +// validateHTTPHeaderMatches validates that no header name +// is matched more than once (case-insensitive). +func validateHTTPHeaderMatches(matches []gatewayv1.HTTPHeaderMatch, path *field.Path) field.ErrorList { + var errs field.ErrorList + counts := map[string]int{} + + for _, match := range matches { + // Header names are case-insensitive. + counts[strings.ToLower(string(match.Name))]++ + } + + for name, count := range counts { + if count > 1 { + errs = append(errs, field.Invalid(path, http.CanonicalHeaderKey(name), "cannot match the same header multiple times in the same rule")) + } + } + + return errs +} + +// validateHTTPQueryParamMatches validates that no query param name +// is matched more than once (case-sensitive). +func validateHTTPQueryParamMatches(matches []gatewayv1.HTTPQueryParamMatch, path *field.Path) field.ErrorList { + var errs field.ErrorList + counts := map[string]int{} + + for _, match := range matches { + // Query param names are case-sensitive. + counts[string(match.Name)]++ + } + + for name, count := range counts { + if count > 1 { + errs = append(errs, field.Invalid(path, name, "cannot match the same query parameter multiple times in the same rule")) + } + } + + return errs +} + +// validateHTTPRouteFilterTypeMatchesValue validates that only the expected fields are +// set for the specified filter type. +func validateHTTPRouteFilterTypeMatchesValue(filter gatewayv1.HTTPRouteFilter, path *field.Path) field.ErrorList { + var errs field.ErrorList + if filter.ExtensionRef != nil && filter.Type != gatewayv1.HTTPRouteFilterExtensionRef { + errs = append(errs, field.Invalid(path, filter.ExtensionRef, "must be nil if the HTTPRouteFilter.Type is not ExtensionRef")) + } + if filter.ExtensionRef == nil && filter.Type == gatewayv1.HTTPRouteFilterExtensionRef { + errs = append(errs, field.Required(path, "filter.ExtensionRef must be specified for ExtensionRef HTTPRouteFilter.Type")) + } + if filter.RequestHeaderModifier != nil && filter.Type != gatewayv1.HTTPRouteFilterRequestHeaderModifier { + errs = append(errs, field.Invalid(path, filter.RequestHeaderModifier, "must be nil if the HTTPRouteFilter.Type is not RequestHeaderModifier")) + } + if filter.RequestHeaderModifier == nil && filter.Type == gatewayv1.HTTPRouteFilterRequestHeaderModifier { + errs = append(errs, field.Required(path, "filter.RequestHeaderModifier must be specified for RequestHeaderModifier HTTPRouteFilter.Type")) + } + if filter.ResponseHeaderModifier != nil && filter.Type != gatewayv1.HTTPRouteFilterResponseHeaderModifier { + errs = append(errs, field.Invalid(path, filter.ResponseHeaderModifier, "must be nil if the HTTPRouteFilter.Type is not ResponseHeaderModifier")) + } + if filter.ResponseHeaderModifier == nil && filter.Type == gatewayv1.HTTPRouteFilterResponseHeaderModifier { + errs = append(errs, field.Required(path, "filter.ResponseHeaderModifier must be specified for ResponseHeaderModifier HTTPRouteFilter.Type")) + } + if filter.RequestMirror != nil && filter.Type != gatewayv1.HTTPRouteFilterRequestMirror { + errs = append(errs, field.Invalid(path, filter.RequestMirror, "must be nil if the HTTPRouteFilter.Type is not RequestMirror")) + } + if filter.RequestMirror == nil && filter.Type == gatewayv1.HTTPRouteFilterRequestMirror { + errs = append(errs, field.Required(path, "filter.RequestMirror must be specified for RequestMirror HTTPRouteFilter.Type")) + } + if filter.RequestRedirect != nil && filter.Type != gatewayv1.HTTPRouteFilterRequestRedirect { + errs = append(errs, field.Invalid(path, filter.RequestRedirect, "must be nil if the HTTPRouteFilter.Type is not RequestRedirect")) + } + if filter.RequestRedirect == nil && filter.Type == gatewayv1.HTTPRouteFilterRequestRedirect { + errs = append(errs, field.Required(path, "filter.RequestRedirect must be specified for RequestRedirect HTTPRouteFilter.Type")) + } + if filter.URLRewrite != nil && filter.Type != gatewayv1.HTTPRouteFilterURLRewrite { + errs = append(errs, field.Invalid(path, filter.URLRewrite, "must be nil if the HTTPRouteFilter.Type is not URLRewrite")) + } + if filter.URLRewrite == nil && filter.Type == gatewayv1.HTTPRouteFilterURLRewrite { + errs = append(errs, field.Required(path, "filter.URLRewrite must be specified for URLRewrite HTTPRouteFilter.Type")) + } + return errs +} + +// validateHTTPPathModifier validates that only the expected fields are set in a +// path modifier. +func validateHTTPPathModifier(modifier gatewayv1.HTTPPathModifier, matches []gatewayv1.HTTPRouteMatch, path *field.Path) field.ErrorList { + var errs field.ErrorList + if modifier.ReplaceFullPath != nil && modifier.Type != gatewayv1.FullPathHTTPPathModifier { + errs = append(errs, field.Invalid(path, modifier.ReplaceFullPath, "must be nil if the HTTPRouteFilter.Type is not ReplaceFullPath")) + } + if modifier.ReplaceFullPath == nil && modifier.Type == gatewayv1.FullPathHTTPPathModifier { + errs = append(errs, field.Invalid(path, modifier.ReplaceFullPath, "must not be nil if the HTTPRouteFilter.Type is ReplaceFullPath")) + } + if modifier.ReplacePrefixMatch != nil && modifier.Type != gatewayv1.PrefixMatchHTTPPathModifier { + errs = append(errs, field.Invalid(path, modifier.ReplacePrefixMatch, "must be nil if the HTTPRouteFilter.Type is not ReplacePrefixMatch")) + } + if modifier.ReplacePrefixMatch == nil && modifier.Type == gatewayv1.PrefixMatchHTTPPathModifier { + errs = append(errs, field.Invalid(path, modifier.ReplacePrefixMatch, "must not be nil if the HTTPRouteFilter.Type is ReplacePrefixMatch")) + } + + if modifier.Type == gatewayv1.PrefixMatchHTTPPathModifier && modifier.ReplacePrefixMatch != nil { + if !hasExactlyOnePrefixMatch(matches) { + errs = append(errs, field.Invalid(path, modifier.ReplacePrefixMatch, "exactly one PathPrefix match must be specified to use this path modifier")) + } + } + return errs +} + +func validateHTTPHeaderModifier(filter gatewayv1.HTTPHeaderFilter, path *field.Path) field.ErrorList { + var errs field.ErrorList + singleAction := make(map[string]bool) + for i, action := range filter.Add { + if needsErr, ok := singleAction[strings.ToLower(string(action.Name))]; ok { + if needsErr { + errs = append(errs, field.Invalid(path.Child("add"), filter.Add[i], "cannot specify multiple actions for header")) + } + singleAction[strings.ToLower(string(action.Name))] = false + } else { + singleAction[strings.ToLower(string(action.Name))] = true + } + } + for i, action := range filter.Set { + if needsErr, ok := singleAction[strings.ToLower(string(action.Name))]; ok { + if needsErr { + errs = append(errs, field.Invalid(path.Child("set"), filter.Set[i], "cannot specify multiple actions for header")) + } + singleAction[strings.ToLower(string(action.Name))] = false + } else { + singleAction[strings.ToLower(string(action.Name))] = true + } + } + for i, name := range filter.Remove { + if needsErr, ok := singleAction[strings.ToLower(name)]; ok { + if needsErr { + errs = append(errs, field.Invalid(path.Child("remove"), filter.Remove[i], "cannot specify multiple actions for header")) + } + singleAction[strings.ToLower(name)] = false + } else { + singleAction[strings.ToLower(name)] = true + } + } + return errs +} + +func validateHTTPRouteTimeouts(timeouts *gatewayv1.HTTPRouteTimeouts, path *field.Path) field.ErrorList { + var errs field.ErrorList + if timeouts.BackendRequest != nil { + backendTimeout, _ := time.ParseDuration((string)(*timeouts.BackendRequest)) + if timeouts.Request != nil { + timeout, _ := time.ParseDuration((string)(*timeouts.Request)) + if backendTimeout > timeout && timeout != 0 { + errs = append(errs, field.Invalid(path.Child("backendRequest"), backendTimeout, "backendRequest timeout cannot be longer than request timeout")) + } + } + } + + return errs +} + +func hasExactlyOnePrefixMatch(matches []gatewayv1.HTTPRouteMatch) bool { + if len(matches) != 1 || matches[0].Path == nil { + return false + } + pathMatchType := matches[0].Path.Type + if *pathMatchType != gatewayv1.PathMatchPathPrefix { + return false + } + + return true +} diff --git a/apis/v1/validation/httproute_test.go b/apis/v1/validation/httproute_test.go new file mode 100644 index 0000000000..3eaa466886 --- /dev/null +++ b/apis/v1/validation/httproute_test.go @@ -0,0 +1,1307 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/util/validation/field" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +func TestValidateHTTPRoute(t *testing.T) { + testService := gatewayv1.ObjectName("test-service") + pathPrefixMatchType := gatewayv1.PathMatchPathPrefix + + tests := []struct { + name string + rules []gatewayv1.HTTPRouteRule + errCount int + }{{ + name: "valid httpRoute with no filters", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Matches: []gatewayv1.HTTPRouteMatch{ + { + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), + Value: ptrTo("/"), + }, + }, + }, + BackendRefs: []gatewayv1.HTTPBackendRef{ + { + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: testService, + Port: ptrTo(gatewayv1.PortNumber(8080)), + }, + Weight: ptrTo(int32(100)), + }, + }, + }, + }, + }, + }, { + name: "valid httpRoute with 1 filter", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Matches: []gatewayv1.HTTPRouteMatch{ + { + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), + Value: ptrTo("/"), + }, + }, + }, + Filters: []gatewayv1.HTTPRouteFilter{ + { + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{ + BackendRef: gatewayv1.BackendObjectReference{ + Name: testService, + Port: ptrTo(gatewayv1.PortNumber(8081)), + }, + }, + }, + }, + }, + }, + }, { + name: "invalid httpRoute with 2 extended filters", + errCount: 1, + rules: []gatewayv1.HTTPRouteRule{ + { + Matches: []gatewayv1.HTTPRouteMatch{ + { + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), + Value: ptrTo("/"), + }, + }, + }, + Filters: []gatewayv1.HTTPRouteFilter{ + { + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, + ReplacePrefixMatch: ptrTo("foo"), + }, + }, + }, + { + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, + ReplacePrefixMatch: ptrTo("bar"), + }, + }, + }, + }, + }, + }, + }, { + name: "invalid httpRoute with mix of filters and one duplicate", + errCount: 1, + rules: []gatewayv1.HTTPRouteRule{ + { + Matches: []gatewayv1.HTTPRouteMatch{ + { + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), + Value: ptrTo("/"), + }, + }, + }, + Filters: []gatewayv1.HTTPRouteFilter{ + { + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Set: []gatewayv1.HTTPHeader{ + { + Name: "special-header", + Value: "foo", + }, + }, + }, + }, + { + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{ + BackendRef: gatewayv1.BackendObjectReference{ + Name: testService, + Port: ptrTo(gatewayv1.PortNumber(8080)), + }, + }, + }, + { + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{ + { + Name: "my-header", + Value: "bar", + }, + }, + }, + }, + }, + }, + }, + }, { + name: "invalid httpRoute with multiple duplicate filters", + errCount: 2, + rules: []gatewayv1.HTTPRouteRule{ + { + Matches: []gatewayv1.HTTPRouteMatch{ + { + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), + Value: ptrTo("/"), + }, + }, + }, + Filters: []gatewayv1.HTTPRouteFilter{ + { + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Set: []gatewayv1.HTTPHeader{ + { + Name: "special-header", + Value: "foo", + }, + }, + }, + }, + { + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{ + { + Name: "my-header", + Value: "bar", + }, + }, + }, + }, + { + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, + ResponseHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{ + { + Name: "extra-header", + Value: "foo", + }, + }, + }, + }, + { + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, + ResponseHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Set: []gatewayv1.HTTPHeader{ + { + Name: "other-header", + Value: "bat", + }, + }, + }, + }, + }, + }, + }, + }, { + name: "valid httpRoute with duplicate ExtensionRef filters", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Matches: []gatewayv1.HTTPRouteMatch{ + { + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), + Value: ptrTo("/"), + }, + }, + }, + Filters: []gatewayv1.HTTPRouteFilter{ + { + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Set: []gatewayv1.HTTPHeader{ + { + Name: "special-header", + Value: "foo", + }, + }, + }, + }, + { + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{ + BackendRef: gatewayv1.BackendObjectReference{ + Name: testService, + Port: ptrTo(gatewayv1.PortNumber(8080)), + }, + }, + }, + { + Type: "ExtensionRef", + ExtensionRef: &gatewayv1.LocalObjectReference{ + Kind: "Service", + Name: "test", + }, + }, + { + Type: "ExtensionRef", + ExtensionRef: &gatewayv1.LocalObjectReference{ + Kind: "Service", + Name: "test", + }, + }, + { + Type: "ExtensionRef", + ExtensionRef: &gatewayv1.LocalObjectReference{ + Kind: "Service", + Name: "test", + }, + }, + }, + }, + }, + }, { + name: "valid redirect path modifier", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Filters: []gatewayv1.HTTPRouteFilter{ + { + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.FullPathHTTPPathModifier, + ReplaceFullPath: ptrTo("foo"), + }, + }, + }, + }, + }, + }, + }, { + name: "redirect path modifier with type mismatch", + errCount: 2, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, + ReplaceFullPath: ptrTo("foo"), + }, + }, + }}, + }}, + }, { + name: "valid rewrite path modifier", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{{ + Path: &gatewayv1.HTTPPathMatch{ + Type: &pathPrefixMatchType, + Value: ptrTo("/bar"), + }, + }}, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, + ReplacePrefixMatch: ptrTo("foo"), + }, + }, + }}, + }}, + }, { + name: "rewrite path modifier missing path match", + errCount: 1, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, + ReplacePrefixMatch: ptrTo("foo"), + }, + }, + }}, + }}, + }, { + name: "rewrite path too many matches", + errCount: 1, + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{{ + Path: &gatewayv1.HTTPPathMatch{ + Type: &pathPrefixMatchType, + Value: ptrTo("/foo"), + }, + }, { + Path: &gatewayv1.HTTPPathMatch{ + Type: &pathPrefixMatchType, + Value: ptrTo("/bar"), + }, + }}, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, + ReplacePrefixMatch: ptrTo("foo"), + }, + }, + }}, + }}, + }, { + name: "redirect path modifier with type mismatch", + errCount: 2, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.FullPathHTTPPathModifier, + ReplacePrefixMatch: ptrTo("foo"), + }, + }, + }}, + }}, + }, { + name: "rewrite and redirect filters combined (invalid)", + errCount: 3, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, + ReplacePrefixMatch: ptrTo("foo"), + }, + }, + }, { + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, + ReplacePrefixMatch: ptrTo("foo"), + }, + }, + }}, + }}, + }, { + name: "multiple actions for the same request header (invalid)", + errCount: 2, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{ + { + Name: gatewayv1.HTTPHeaderName("x-fruit"), + Value: "apple", + }, + { + Name: gatewayv1.HTTPHeaderName("x-vegetable"), + Value: "carrot", + }, + { + Name: gatewayv1.HTTPHeaderName("x-grain"), + Value: "rye", + }, + }, + Set: []gatewayv1.HTTPHeader{ + { + Name: gatewayv1.HTTPHeaderName("x-fruit"), + Value: "watermelon", + }, + { + Name: gatewayv1.HTTPHeaderName("x-grain"), + Value: "wheat", + }, + { + Name: gatewayv1.HTTPHeaderName("x-spice"), + Value: "coriander", + }, + }, + }, + }}, + }}, + }, { + name: "multiple actions for the same request header with inconsistent case (invalid)", + errCount: 1, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{ + { + Name: gatewayv1.HTTPHeaderName("x-fruit"), + Value: "apple", + }, + }, + Set: []gatewayv1.HTTPHeader{ + { + Name: gatewayv1.HTTPHeaderName("X-Fruit"), + Value: "watermelon", + }, + }, + }, + }}, + }}, + }, { + name: "multiple of the same action for the same request header (invalid)", + errCount: 1, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{ + { + Name: gatewayv1.HTTPHeaderName("x-fruit"), + Value: "apple", + }, + { + Name: gatewayv1.HTTPHeaderName("x-fruit"), + Value: "plum", + }, + }, + }, + }}, + }}, + }, { + name: "multiple actions for different request headers", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{ + { + Name: gatewayv1.HTTPHeaderName("x-vegetable"), + Value: "carrot", + }, + { + Name: gatewayv1.HTTPHeaderName("x-grain"), + Value: "rye", + }, + }, + Set: []gatewayv1.HTTPHeader{ + { + Name: gatewayv1.HTTPHeaderName("x-fruit"), + Value: "watermelon", + }, + { + Name: gatewayv1.HTTPHeaderName("x-spice"), + Value: "coriander", + }, + }, + }, + }}, + }}, + }, { + name: "multiple actions for the same response header (invalid)", + errCount: 1, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, + ResponseHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{{ + Name: gatewayv1.HTTPHeaderName("x-example"), + Value: "blueberry", + }}, + Set: []gatewayv1.HTTPHeader{{ + Name: gatewayv1.HTTPHeaderName("x-example"), + Value: "turnip", + }}, + }, + }}, + }}, + }, { + name: "multiple actions for different response headers", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, + ResponseHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{{ + Name: gatewayv1.HTTPHeaderName("x-example"), + Value: "blueberry", + }}, + Set: []gatewayv1.HTTPHeader{{ + Name: gatewayv1.HTTPHeaderName("x-different"), + Value: "turnip", + }}, + }, + }}, + }}, + }} + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + var errs field.ErrorList + route := gatewayv1.HTTPRoute{Spec: gatewayv1.HTTPRouteSpec{Rules: tc.rules}} + errs = ValidateHTTPRoute(&route) + if len(errs) != tc.errCount { + t.Errorf("got %d errors, want %d errors: %s", len(errs), tc.errCount, errs) + } + }) + } +} + +func TestValidateHTTPBackendUniqueFilters(t *testing.T) { + var testService gatewayv1.ObjectName = "testService" + var specialService gatewayv1.ObjectName = "specialService" + tests := []struct { + name string + rules []gatewayv1.HTTPRouteRule + errCount int + }{{ + name: "valid httpRoute Rules backendref filters", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{{ + BackendRefs: []gatewayv1.HTTPBackendRef{ + { + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: testService, + Port: ptrTo(gatewayv1.PortNumber(8080)), + }, + Weight: ptrTo(int32(100)), + }, + Filters: []gatewayv1.HTTPRouteFilter{ + { + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{ + BackendRef: gatewayv1.BackendObjectReference{ + Name: testService, + Port: ptrTo(gatewayv1.PortNumber(8080)), + }, + }, + }, + }, + }, + }, + }}, + }, { + name: "valid httpRoute Rules duplicate mirror filter", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{{ + BackendRefs: []gatewayv1.HTTPBackendRef{ + { + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: testService, + Port: ptrTo(gatewayv1.PortNumber(8080)), + }, + }, + Filters: []gatewayv1.HTTPRouteFilter{ + { + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{ + BackendRef: gatewayv1.BackendObjectReference{ + Name: testService, + Port: ptrTo(gatewayv1.PortNumber(8080)), + }, + }, + }, + { + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{ + BackendRef: gatewayv1.BackendObjectReference{ + Name: specialService, + Port: ptrTo(gatewayv1.PortNumber(8080)), + }, + }, + }, + }, + }, + }, + }}, + }} + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + route := gatewayv1.HTTPRoute{Spec: gatewayv1.HTTPRouteSpec{Rules: tc.rules}} + errs := ValidateHTTPRoute(&route) + if len(errs) != tc.errCount { + t.Errorf("got %d errors, want %d errors: %s", len(errs), tc.errCount, errs) + } + }) + } +} + +func TestValidateHTTPPathMatch(t *testing.T) { + tests := []struct { + name string + path *gatewayv1.HTTPPathMatch + errCount int + }{{ + name: "invalid httpRoute prefix (/.)", + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), + Value: ptrTo("/."), + }, + errCount: 1, + }, { + name: "invalid exact (/./)", + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("Exact")), + Value: ptrTo("/foo/./bar"), + }, + errCount: 1, + }, { + name: "valid httpRoute prefix", + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), + Value: ptrTo("/"), + }, + errCount: 0, + }, { + name: "invalid httpRoute prefix (/[])", + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), + Value: ptrTo("/[]"), + }, + errCount: 1, + }, { + name: "invalid httpRoute exact (/^)", + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("Exact")), + Value: ptrTo("/^"), + }, + errCount: 1, + }} + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + route := gatewayv1.HTTPRoute{Spec: gatewayv1.HTTPRouteSpec{ + Rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{{ + Path: tc.path, + }}, + BackendRefs: []gatewayv1.HTTPBackendRef{{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: gatewayv1.ObjectName("test"), + Port: ptrTo(gatewayv1.PortNumber(8080)), + }, + }, + }}, + }}, + }} + + errs := ValidateHTTPRoute(&route) + if len(errs) != tc.errCount { + t.Errorf("got %d errors, want %d errors: %s", len(errs), tc.errCount, errs) + } + }) + } +} + +func TestValidateHTTPHeaderMatches(t *testing.T) { + tests := []struct { + name string + headerMatches []gatewayv1.HTTPHeaderMatch + expectErr string + }{{ + name: "no header matches", + headerMatches: nil, + expectErr: "", + }, { + name: "no header matched more than once", + headerMatches: []gatewayv1.HTTPHeaderMatch{ + {Name: "Header-Name-1", Value: "val-1"}, + {Name: "Header-Name-2", Value: "val-2"}, + {Name: "Header-Name-3", Value: "val-3"}, + }, + expectErr: "", + }, { + name: "header matched more than once (same case)", + headerMatches: []gatewayv1.HTTPHeaderMatch{ + {Name: "Header-Name-1", Value: "val-1"}, + {Name: "Header-Name-2", Value: "val-2"}, + {Name: "Header-Name-1", Value: "val-3"}, + }, + expectErr: "spec.rules[0].matches[0].headers: Invalid value: \"Header-Name-1\": cannot match the same header multiple times in the same rule", + }, { + name: "header matched more than once (different case)", + headerMatches: []gatewayv1.HTTPHeaderMatch{ + {Name: "Header-Name-1", Value: "val-1"}, + {Name: "Header-Name-2", Value: "val-2"}, + {Name: "HEADER-NAME-2", Value: "val-3"}, + }, + expectErr: "spec.rules[0].matches[0].headers: Invalid value: \"Header-Name-2\": cannot match the same header multiple times in the same rule", + }} + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + route := gatewayv1.HTTPRoute{Spec: gatewayv1.HTTPRouteSpec{ + Rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{{ + Headers: tc.headerMatches, + }}, + BackendRefs: []gatewayv1.HTTPBackendRef{{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: gatewayv1.ObjectName("test"), + Port: ptrTo(gatewayv1.PortNumber(8080)), + }, + }, + }}, + }}, + }} + + errs := ValidateHTTPRoute(&route) + if len(tc.expectErr) == 0 { + assert.Emptyf(t, errs, "expected no errors, got %d errors: %s", len(errs), errs) + } else { + require.Lenf(t, errs, 1, "expected one error, got %d errors: %s", len(errs), errs) + assert.Equal(t, tc.expectErr, errs[0].Error()) + } + }) + } +} + +func TestValidateHTTPQueryParamMatches(t *testing.T) { + tests := []struct { + name string + queryParamMatches []gatewayv1.HTTPQueryParamMatch + expectErr string + }{{ + name: "no query param matches", + queryParamMatches: nil, + expectErr: "", + }, { + name: "no query param matched more than once", + queryParamMatches: []gatewayv1.HTTPQueryParamMatch{ + {Name: "query-param-1", Value: "val-1"}, + {Name: "query-param-2", Value: "val-2"}, + {Name: "query-param-3", Value: "val-3"}, + }, + expectErr: "", + }, { + name: "query param matched more than once", + queryParamMatches: []gatewayv1.HTTPQueryParamMatch{ + {Name: "query-param-1", Value: "val-1"}, + {Name: "query-param-2", Value: "val-2"}, + {Name: "query-param-1", Value: "val-3"}, + }, + expectErr: "spec.rules[0].matches[0].queryParams: Invalid value: \"query-param-1\": cannot match the same query parameter multiple times in the same rule", + }, { + name: "query param names with different casing are not considered duplicates", + queryParamMatches: []gatewayv1.HTTPQueryParamMatch{ + {Name: "query-param-1", Value: "val-1"}, + {Name: "query-param-2", Value: "val-2"}, + {Name: "QUERY-PARAM-1", Value: "val-3"}, + }, + expectErr: "", + }} + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + route := gatewayv1.HTTPRoute{Spec: gatewayv1.HTTPRouteSpec{ + Rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{{ + QueryParams: tc.queryParamMatches, + }}, + BackendRefs: []gatewayv1.HTTPBackendRef{{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: gatewayv1.ObjectName("test"), + Port: ptrTo(gatewayv1.PortNumber(8080)), + }, + }, + }}, + }}, + }} + + errs := ValidateHTTPRoute(&route) + if len(tc.expectErr) == 0 { + assert.Emptyf(t, errs, "expected no errors, got %d errors: %s", len(errs), errs) + } else { + require.Lenf(t, errs, 1, "expected one error, got %d errors: %s", len(errs), errs) + assert.Equal(t, tc.expectErr, errs[0].Error()) + } + }) + } +} + +func TestValidateServicePort(t *testing.T) { + portPtr := func(n int) *gatewayv1.PortNumber { + p := gatewayv1.PortNumber(n) + return &p + } + + groupPtr := func(g string) *gatewayv1.Group { + p := gatewayv1.Group(g) + return &p + } + + kindPtr := func(k string) *gatewayv1.Kind { + p := gatewayv1.Kind(k) + return &p + } + + tests := []struct { + name string + rules []gatewayv1.HTTPRouteRule + errCount int + }{{ + name: "default groupkind with port", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{{ + BackendRefs: []gatewayv1.HTTPBackendRef{{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: "backend", + Port: portPtr(99), + }, + }, + }}, + }}, + }, { + name: "default groupkind with no port", + errCount: 1, + rules: []gatewayv1.HTTPRouteRule{{ + BackendRefs: []gatewayv1.HTTPBackendRef{{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: "backend", + }, + }, + }}, + }}, + }, { + name: "explicit service with port", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{{ + BackendRefs: []gatewayv1.HTTPBackendRef{{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Group: groupPtr(""), + Kind: kindPtr("Service"), + Name: "backend", + Port: portPtr(99), + }, + }, + }}, + }}, + }, { + name: "explicit service with no port", + errCount: 1, + rules: []gatewayv1.HTTPRouteRule{{ + BackendRefs: []gatewayv1.HTTPBackendRef{{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Group: groupPtr(""), + Kind: kindPtr("Service"), + Name: "backend", + }, + }, + }}, + }}, + }, { + name: "explicit ref with no port", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{{ + BackendRefs: []gatewayv1.HTTPBackendRef{{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Group: groupPtr("foo.example.com"), + Kind: kindPtr("Foo"), + Name: "backend", + }, + }, + }}, + }}, + }} + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + route := gatewayv1.HTTPRoute{Spec: gatewayv1.HTTPRouteSpec{Rules: tc.rules}} + errs := ValidateHTTPRoute(&route) + if len(errs) != tc.errCount { + t.Errorf("got %d errors, want %d errors: %s", len(errs), tc.errCount, errs) + } + }) + } +} + +func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { + tests := []struct { + name string + routeFilter gatewayv1.HTTPRouteFilter + errCount int + }{{ + name: "valid HTTPRouteFilterRequestHeaderModifier route filter", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Set: []gatewayv1.HTTPHeader{{Name: "name"}}, + Add: []gatewayv1.HTTPHeader{{Name: "add"}}, + Remove: []string{"remove"}, + }, + }, + errCount: 0, + }, { + name: "invalid HTTPRouteFilterRequestHeaderModifier type filter with non-matching field", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{}, + }, + errCount: 2, + }, { + name: "invalid HTTPRouteFilterRequestHeaderModifier type filter with empty value field", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + }, + errCount: 1, + }, { + name: "valid HTTPRouteFilterRequestMirror route filter", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{BackendRef: gatewayv1.BackendObjectReference{ + Group: new(gatewayv1.Group), + Kind: new(gatewayv1.Kind), + Name: "name", + Namespace: new(gatewayv1.Namespace), + Port: ptrTo(gatewayv1.PortNumber(22)), + }}, + }, + errCount: 0, + }, { + name: "invalid HTTPRouteFilterRequestMirror type filter with non-matching field", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{}, + }, + errCount: 2, + }, { + name: "invalid HTTPRouteFilterRequestMirror type filter with empty value field", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestMirror, + }, + errCount: 1, + }, { + name: "valid HTTPRouteFilterRequestRedirect route filter", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Scheme: new(string), + Hostname: new(gatewayv1.PreciseHostname), + Path: &gatewayv1.HTTPPathModifier{}, + Port: new(gatewayv1.PortNumber), + StatusCode: new(int), + }, + }, + errCount: 1, + }, { + name: "invalid HTTPRouteFilterRequestRedirect type filter with non-matching field", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{}, + }, + errCount: 2, + }, { + name: "invalid HTTPRouteFilterRequestRedirect type filter with empty value field", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + }, + errCount: 1, + }, { + name: "valid HTTPRouteFilterExtensionRef filter", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterExtensionRef, + ExtensionRef: &gatewayv1.LocalObjectReference{ + Group: "group", + Kind: "kind", + Name: "name", + }, + }, + errCount: 0, + }, { + name: "invalid HTTPRouteFilterExtensionRef type filter with non-matching field", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterExtensionRef, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{}, + }, + errCount: 2, + }, { + name: "invalid HTTPRouteFilterExtensionRef type filter with empty value field", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterExtensionRef, + }, + errCount: 1, + }, { + name: "valid HTTPRouteFilterURLRewrite route filter", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Hostname: new(gatewayv1.PreciseHostname), + Path: &gatewayv1.HTTPPathModifier{}, + }, + }, + errCount: 0, + }, { + name: "invalid HTTPRouteFilterURLRewrite type filter with non-matching field", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{}, + }, + errCount: 2, + }, { + name: "invalid HTTPRouteFilterURLRewrite type filter with empty value field", + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + }, + errCount: 1, + }, { + name: "empty type filter is valid (caught by CRD validation)", + routeFilter: gatewayv1.HTTPRouteFilter{}, + errCount: 0, + }} + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + route := gatewayv1.HTTPRoute{ + Spec: gatewayv1.HTTPRouteSpec{ + Rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{tc.routeFilter}, + BackendRefs: []gatewayv1.HTTPBackendRef{{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: gatewayv1.ObjectName("test"), + Port: ptrTo(gatewayv1.PortNumber(8080)), + }, + }, + }}, + }}, + }, + } + errs := ValidateHTTPRoute(&route) + if len(errs) != tc.errCount { + t.Errorf("got %d errors, want %d errors: %s", len(errs), tc.errCount, errs) + } + }) + } +} + +func TestValidateRequestRedirectFiltersWithNoBackendRef(t *testing.T) { + testService := gatewayv1.ObjectName("test-service") + tests := []struct { + name string + rules []gatewayv1.HTTPRouteRule + errCount int + }{ + { + name: "backendref with request redirect httpRoute filter", + errCount: 1, + rules: []gatewayv1.HTTPRouteRule{ + { + Filters: []gatewayv1.HTTPRouteFilter{ + { + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Scheme: ptrTo("https"), + StatusCode: ptrTo(301), + }, + }, + }, + BackendRefs: []gatewayv1.HTTPBackendRef{ + { + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: testService, + Port: ptrTo(gatewayv1.PortNumber(80)), + }, + }, + }, + }, + }, + }, + }, { + name: "request redirect without backendref in httpRoute filter", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Filters: []gatewayv1.HTTPRouteFilter{ + { + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Scheme: ptrTo("https"), + StatusCode: ptrTo(301), + }, + }, + }, + }, + }, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + var errs field.ErrorList + route := gatewayv1.HTTPRoute{Spec: gatewayv1.HTTPRouteSpec{Rules: tc.rules}} + errs = ValidateHTTPRoute(&route) + if len(errs) != tc.errCount { + t.Errorf("got %d errors, want %d errors: %s", len(errs), tc.errCount, errs) + } + }) + } +} + +func toDuration(durationString string) *gatewayv1.Duration { + return (*gatewayv1.Duration)(&durationString) +} + +func TestValidateHTTPTimeouts(t *testing.T) { + tests := []struct { + name string + rules []gatewayv1.HTTPRouteRule + errCount int + }{ + { + name: "valid httpRoute Rules timeouts", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Timeouts: &gatewayv1.HTTPRouteTimeouts{ + Request: toDuration("1ms"), + }, + }, + }, + }, { + name: "valid httpRoute Rules timeout set to 0s (disabled)", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Timeouts: &gatewayv1.HTTPRouteTimeouts{ + Request: toDuration("0s"), + }, + }, + }, + }, { + name: "valid httpRoute Rules timeout set to 0ms (disabled)", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Timeouts: &gatewayv1.HTTPRouteTimeouts{ + Request: toDuration("0ms"), + }, + }, + }, + }, {}, { + name: "valid httpRoute Rules timeout set to 0h (disabled)", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Timeouts: &gatewayv1.HTTPRouteTimeouts{ + Request: toDuration("0h"), + }, + }, + }, + }, { + name: "valid httpRoute Rules timeout and backendRequest have the same value", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Timeouts: &gatewayv1.HTTPRouteTimeouts{ + Request: toDuration("1ms"), + BackendRequest: toDuration("1ms"), + }, + }, + }, + }, { + name: "invalid httpRoute Rules backendRequest timeout cannot be longer than request timeout", + errCount: 1, + rules: []gatewayv1.HTTPRouteRule{ + { + Timeouts: &gatewayv1.HTTPRouteTimeouts{ + Request: toDuration("1ms"), + BackendRequest: toDuration("2ms"), + }, + }, + }, + }, { + name: "valid httpRoute Rules request timeout 1s and backendRequest timeout 200ms", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Timeouts: &gatewayv1.HTTPRouteTimeouts{ + Request: toDuration("1s"), + BackendRequest: toDuration("200ms"), + }, + }, + }, + }, { + name: "valid httpRoute Rules request timeout 10s and backendRequest timeout 10s", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Timeouts: &gatewayv1.HTTPRouteTimeouts{ + Request: toDuration("10s"), + BackendRequest: toDuration("10s"), + }, + }, + }, + }, { + name: "invalid httpRoute Rules backendRequest timeout cannot be greater than request timeout", + errCount: 1, + rules: []gatewayv1.HTTPRouteRule{ + { + Timeouts: &gatewayv1.HTTPRouteTimeouts{ + Request: toDuration("200ms"), + BackendRequest: toDuration("1s"), + }, + }, + }, + }, { + name: "valid httpRoute Rules request 0s (infinite) and backendRequest 100ms", + errCount: 0, + rules: []gatewayv1.HTTPRouteRule{ + { + Timeouts: &gatewayv1.HTTPRouteTimeouts{ + Request: toDuration("0s"), + BackendRequest: toDuration("100ms"), + }, + }, + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + route := gatewayv1.HTTPRoute{Spec: gatewayv1.HTTPRouteSpec{Rules: tc.rules}} + errs := ValidateHTTPRoute(&route) + if len(errs) != tc.errCount { + t.Errorf("got %d errors, want %d errors: %s", len(errs), tc.errCount, errs) + } + }) + } +} diff --git a/apis/v1/zz_generated.deepcopy.go b/apis/v1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..25fadfa894 --- /dev/null +++ b/apis/v1/zz_generated.deepcopy.go @@ -0,0 +1,1216 @@ +//go:build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AllowedRoutes) DeepCopyInto(out *AllowedRoutes) { + *out = *in + if in.Namespaces != nil { + in, out := &in.Namespaces, &out.Namespaces + *out = new(RouteNamespaces) + (*in).DeepCopyInto(*out) + } + if in.Kinds != nil { + in, out := &in.Kinds, &out.Kinds + *out = make([]RouteGroupKind, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllowedRoutes. +func (in *AllowedRoutes) DeepCopy() *AllowedRoutes { + if in == nil { + return nil + } + out := new(AllowedRoutes) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendObjectReference) DeepCopyInto(out *BackendObjectReference) { + *out = *in + if in.Group != nil { + in, out := &in.Group, &out.Group + *out = new(Group) + **out = **in + } + if in.Kind != nil { + in, out := &in.Kind, &out.Kind + *out = new(Kind) + **out = **in + } + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(Namespace) + **out = **in + } + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(PortNumber) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendObjectReference. +func (in *BackendObjectReference) DeepCopy() *BackendObjectReference { + if in == nil { + return nil + } + out := new(BackendObjectReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendRef) DeepCopyInto(out *BackendRef) { + *out = *in + in.BackendObjectReference.DeepCopyInto(&out.BackendObjectReference) + if in.Weight != nil { + in, out := &in.Weight, &out.Weight + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendRef. +func (in *BackendRef) DeepCopy() *BackendRef { + if in == nil { + return nil + } + out := new(BackendRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommonRouteSpec) DeepCopyInto(out *CommonRouteSpec) { + *out = *in + if in.ParentRefs != nil { + in, out := &in.ParentRefs, &out.ParentRefs + *out = make([]ParentReference, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonRouteSpec. +func (in *CommonRouteSpec) DeepCopy() *CommonRouteSpec { + if in == nil { + return nil + } + out := new(CommonRouteSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Gateway) DeepCopyInto(out *Gateway) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Gateway. +func (in *Gateway) DeepCopy() *Gateway { + if in == nil { + return nil + } + out := new(Gateway) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Gateway) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayAddress) DeepCopyInto(out *GatewayAddress) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(AddressType) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayAddress. +func (in *GatewayAddress) DeepCopy() *GatewayAddress { + if in == nil { + return nil + } + out := new(GatewayAddress) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayClass) DeepCopyInto(out *GatewayClass) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClass. +func (in *GatewayClass) DeepCopy() *GatewayClass { + if in == nil { + return nil + } + out := new(GatewayClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GatewayClass) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayClassList) DeepCopyInto(out *GatewayClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GatewayClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassList. +func (in *GatewayClassList) DeepCopy() *GatewayClassList { + if in == nil { + return nil + } + out := new(GatewayClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GatewayClassList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayClassSpec) DeepCopyInto(out *GatewayClassSpec) { + *out = *in + if in.ParametersRef != nil { + in, out := &in.ParametersRef, &out.ParametersRef + *out = new(ParametersReference) + (*in).DeepCopyInto(*out) + } + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassSpec. +func (in *GatewayClassSpec) DeepCopy() *GatewayClassSpec { + if in == nil { + return nil + } + out := new(GatewayClassSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayClassStatus) DeepCopyInto(out *GatewayClassStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.SupportedFeatures != nil { + in, out := &in.SupportedFeatures, &out.SupportedFeatures + *out = make([]SupportedFeature, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassStatus. +func (in *GatewayClassStatus) DeepCopy() *GatewayClassStatus { + if in == nil { + return nil + } + out := new(GatewayClassStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayInfrastructure) DeepCopyInto(out *GatewayInfrastructure) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[AnnotationKey]AnnotationValue, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[AnnotationKey]AnnotationValue, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayInfrastructure. +func (in *GatewayInfrastructure) DeepCopy() *GatewayInfrastructure { + if in == nil { + return nil + } + out := new(GatewayInfrastructure) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayList) DeepCopyInto(out *GatewayList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Gateway, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayList. +func (in *GatewayList) DeepCopy() *GatewayList { + if in == nil { + return nil + } + out := new(GatewayList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GatewayList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewaySpec) DeepCopyInto(out *GatewaySpec) { + *out = *in + if in.Listeners != nil { + in, out := &in.Listeners, &out.Listeners + *out = make([]Listener, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]GatewayAddress, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.Infrastructure.DeepCopyInto(&out.Infrastructure) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewaySpec. +func (in *GatewaySpec) DeepCopy() *GatewaySpec { + if in == nil { + return nil + } + out := new(GatewaySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayStatus) DeepCopyInto(out *GatewayStatus) { + *out = *in + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]GatewayStatusAddress, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Listeners != nil { + in, out := &in.Listeners, &out.Listeners + *out = make([]ListenerStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayStatus. +func (in *GatewayStatus) DeepCopy() *GatewayStatus { + if in == nil { + return nil + } + out := new(GatewayStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayStatusAddress) DeepCopyInto(out *GatewayStatusAddress) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(AddressType) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayStatusAddress. +func (in *GatewayStatusAddress) DeepCopy() *GatewayStatusAddress { + if in == nil { + return nil + } + out := new(GatewayStatusAddress) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayTLSConfig) DeepCopyInto(out *GatewayTLSConfig) { + *out = *in + if in.Mode != nil { + in, out := &in.Mode, &out.Mode + *out = new(TLSModeType) + **out = **in + } + if in.CertificateRefs != nil { + in, out := &in.CertificateRefs, &out.CertificateRefs + *out = make([]SecretObjectReference, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Options != nil { + in, out := &in.Options, &out.Options + *out = make(map[AnnotationKey]AnnotationValue, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayTLSConfig. +func (in *GatewayTLSConfig) DeepCopy() *GatewayTLSConfig { + if in == nil { + return nil + } + out := new(GatewayTLSConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPBackendRef) DeepCopyInto(out *HTTPBackendRef) { + *out = *in + in.BackendRef.DeepCopyInto(&out.BackendRef) + if in.Filters != nil { + in, out := &in.Filters, &out.Filters + *out = make([]HTTPRouteFilter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPBackendRef. +func (in *HTTPBackendRef) DeepCopy() *HTTPBackendRef { + if in == nil { + return nil + } + out := new(HTTPBackendRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPHeader) DeepCopyInto(out *HTTPHeader) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeader. +func (in *HTTPHeader) DeepCopy() *HTTPHeader { + if in == nil { + return nil + } + out := new(HTTPHeader) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPHeaderFilter) DeepCopyInto(out *HTTPHeaderFilter) { + *out = *in + if in.Set != nil { + in, out := &in.Set, &out.Set + *out = make([]HTTPHeader, len(*in)) + copy(*out, *in) + } + if in.Add != nil { + in, out := &in.Add, &out.Add + *out = make([]HTTPHeader, len(*in)) + copy(*out, *in) + } + if in.Remove != nil { + in, out := &in.Remove, &out.Remove + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeaderFilter. +func (in *HTTPHeaderFilter) DeepCopy() *HTTPHeaderFilter { + if in == nil { + return nil + } + out := new(HTTPHeaderFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPHeaderMatch) DeepCopyInto(out *HTTPHeaderMatch) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(HeaderMatchType) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeaderMatch. +func (in *HTTPHeaderMatch) DeepCopy() *HTTPHeaderMatch { + if in == nil { + return nil + } + out := new(HTTPHeaderMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPPathMatch) DeepCopyInto(out *HTTPPathMatch) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(PathMatchType) + **out = **in + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPPathMatch. +func (in *HTTPPathMatch) DeepCopy() *HTTPPathMatch { + if in == nil { + return nil + } + out := new(HTTPPathMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPPathModifier) DeepCopyInto(out *HTTPPathModifier) { + *out = *in + if in.ReplaceFullPath != nil { + in, out := &in.ReplaceFullPath, &out.ReplaceFullPath + *out = new(string) + **out = **in + } + if in.ReplacePrefixMatch != nil { + in, out := &in.ReplacePrefixMatch, &out.ReplacePrefixMatch + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPPathModifier. +func (in *HTTPPathModifier) DeepCopy() *HTTPPathModifier { + if in == nil { + return nil + } + out := new(HTTPPathModifier) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPQueryParamMatch) DeepCopyInto(out *HTTPQueryParamMatch) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(QueryParamMatchType) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPQueryParamMatch. +func (in *HTTPQueryParamMatch) DeepCopy() *HTTPQueryParamMatch { + if in == nil { + return nil + } + out := new(HTTPQueryParamMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRequestMirrorFilter) DeepCopyInto(out *HTTPRequestMirrorFilter) { + *out = *in + in.BackendRef.DeepCopyInto(&out.BackendRef) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRequestMirrorFilter. +func (in *HTTPRequestMirrorFilter) DeepCopy() *HTTPRequestMirrorFilter { + if in == nil { + return nil + } + out := new(HTTPRequestMirrorFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRequestRedirectFilter) DeepCopyInto(out *HTTPRequestRedirectFilter) { + *out = *in + if in.Scheme != nil { + in, out := &in.Scheme, &out.Scheme + *out = new(string) + **out = **in + } + if in.Hostname != nil { + in, out := &in.Hostname, &out.Hostname + *out = new(PreciseHostname) + **out = **in + } + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(HTTPPathModifier) + (*in).DeepCopyInto(*out) + } + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(PortNumber) + **out = **in + } + if in.StatusCode != nil { + in, out := &in.StatusCode, &out.StatusCode + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRequestRedirectFilter. +func (in *HTTPRequestRedirectFilter) DeepCopy() *HTTPRequestRedirectFilter { + if in == nil { + return nil + } + out := new(HTTPRequestRedirectFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRoute. +func (in *HTTPRoute) DeepCopy() *HTTPRoute { + if in == nil { + return nil + } + out := new(HTTPRoute) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HTTPRoute) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteFilter) DeepCopyInto(out *HTTPRouteFilter) { + *out = *in + if in.RequestHeaderModifier != nil { + in, out := &in.RequestHeaderModifier, &out.RequestHeaderModifier + *out = new(HTTPHeaderFilter) + (*in).DeepCopyInto(*out) + } + if in.ResponseHeaderModifier != nil { + in, out := &in.ResponseHeaderModifier, &out.ResponseHeaderModifier + *out = new(HTTPHeaderFilter) + (*in).DeepCopyInto(*out) + } + if in.RequestMirror != nil { + in, out := &in.RequestMirror, &out.RequestMirror + *out = new(HTTPRequestMirrorFilter) + (*in).DeepCopyInto(*out) + } + if in.RequestRedirect != nil { + in, out := &in.RequestRedirect, &out.RequestRedirect + *out = new(HTTPRequestRedirectFilter) + (*in).DeepCopyInto(*out) + } + if in.URLRewrite != nil { + in, out := &in.URLRewrite, &out.URLRewrite + *out = new(HTTPURLRewriteFilter) + (*in).DeepCopyInto(*out) + } + if in.ExtensionRef != nil { + in, out := &in.ExtensionRef, &out.ExtensionRef + *out = new(LocalObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteFilter. +func (in *HTTPRouteFilter) DeepCopy() *HTTPRouteFilter { + if in == nil { + return nil + } + out := new(HTTPRouteFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteList) DeepCopyInto(out *HTTPRouteList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]HTTPRoute, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteList. +func (in *HTTPRouteList) DeepCopy() *HTTPRouteList { + if in == nil { + return nil + } + out := new(HTTPRouteList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HTTPRouteList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteMatch) DeepCopyInto(out *HTTPRouteMatch) { + *out = *in + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(HTTPPathMatch) + (*in).DeepCopyInto(*out) + } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]HTTPHeaderMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.QueryParams != nil { + in, out := &in.QueryParams, &out.QueryParams + *out = make([]HTTPQueryParamMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Method != nil { + in, out := &in.Method, &out.Method + *out = new(HTTPMethod) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteMatch. +func (in *HTTPRouteMatch) DeepCopy() *HTTPRouteMatch { + if in == nil { + return nil + } + out := new(HTTPRouteMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteRule) DeepCopyInto(out *HTTPRouteRule) { + *out = *in + if in.Matches != nil { + in, out := &in.Matches, &out.Matches + *out = make([]HTTPRouteMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Filters != nil { + in, out := &in.Filters, &out.Filters + *out = make([]HTTPRouteFilter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.BackendRefs != nil { + in, out := &in.BackendRefs, &out.BackendRefs + *out = make([]HTTPBackendRef, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Timeouts != nil { + in, out := &in.Timeouts, &out.Timeouts + *out = new(HTTPRouteTimeouts) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteRule. +func (in *HTTPRouteRule) DeepCopy() *HTTPRouteRule { + if in == nil { + return nil + } + out := new(HTTPRouteRule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteSpec) DeepCopyInto(out *HTTPRouteSpec) { + *out = *in + in.CommonRouteSpec.DeepCopyInto(&out.CommonRouteSpec) + if in.Hostnames != nil { + in, out := &in.Hostnames, &out.Hostnames + *out = make([]Hostname, len(*in)) + copy(*out, *in) + } + if in.Rules != nil { + in, out := &in.Rules, &out.Rules + *out = make([]HTTPRouteRule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteSpec. +func (in *HTTPRouteSpec) DeepCopy() *HTTPRouteSpec { + if in == nil { + return nil + } + out := new(HTTPRouteSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteStatus) DeepCopyInto(out *HTTPRouteStatus) { + *out = *in + in.RouteStatus.DeepCopyInto(&out.RouteStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteStatus. +func (in *HTTPRouteStatus) DeepCopy() *HTTPRouteStatus { + if in == nil { + return nil + } + out := new(HTTPRouteStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteTimeouts) DeepCopyInto(out *HTTPRouteTimeouts) { + *out = *in + if in.Request != nil { + in, out := &in.Request, &out.Request + *out = new(Duration) + **out = **in + } + if in.BackendRequest != nil { + in, out := &in.BackendRequest, &out.BackendRequest + *out = new(Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteTimeouts. +func (in *HTTPRouteTimeouts) DeepCopy() *HTTPRouteTimeouts { + if in == nil { + return nil + } + out := new(HTTPRouteTimeouts) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPURLRewriteFilter) DeepCopyInto(out *HTTPURLRewriteFilter) { + *out = *in + if in.Hostname != nil { + in, out := &in.Hostname, &out.Hostname + *out = new(PreciseHostname) + **out = **in + } + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(HTTPPathModifier) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPURLRewriteFilter. +func (in *HTTPURLRewriteFilter) DeepCopy() *HTTPURLRewriteFilter { + if in == nil { + return nil + } + out := new(HTTPURLRewriteFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Listener) DeepCopyInto(out *Listener) { + *out = *in + if in.Hostname != nil { + in, out := &in.Hostname, &out.Hostname + *out = new(Hostname) + **out = **in + } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(GatewayTLSConfig) + (*in).DeepCopyInto(*out) + } + if in.AllowedRoutes != nil { + in, out := &in.AllowedRoutes, &out.AllowedRoutes + *out = new(AllowedRoutes) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Listener. +func (in *Listener) DeepCopy() *Listener { + if in == nil { + return nil + } + out := new(Listener) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ListenerStatus) DeepCopyInto(out *ListenerStatus) { + *out = *in + if in.SupportedKinds != nil { + in, out := &in.SupportedKinds, &out.SupportedKinds + *out = make([]RouteGroupKind, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerStatus. +func (in *ListenerStatus) DeepCopy() *ListenerStatus { + if in == nil { + return nil + } + out := new(ListenerStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LocalObjectReference) DeepCopyInto(out *LocalObjectReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalObjectReference. +func (in *LocalObjectReference) DeepCopy() *LocalObjectReference { + if in == nil { + return nil + } + out := new(LocalObjectReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ParametersReference) DeepCopyInto(out *ParametersReference) { + *out = *in + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(Namespace) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParametersReference. +func (in *ParametersReference) DeepCopy() *ParametersReference { + if in == nil { + return nil + } + out := new(ParametersReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ParentReference) DeepCopyInto(out *ParentReference) { + *out = *in + if in.Group != nil { + in, out := &in.Group, &out.Group + *out = new(Group) + **out = **in + } + if in.Kind != nil { + in, out := &in.Kind, &out.Kind + *out = new(Kind) + **out = **in + } + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(Namespace) + **out = **in + } + if in.SectionName != nil { + in, out := &in.SectionName, &out.SectionName + *out = new(SectionName) + **out = **in + } + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(PortNumber) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParentReference. +func (in *ParentReference) DeepCopy() *ParentReference { + if in == nil { + return nil + } + out := new(ParentReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteGroupKind) DeepCopyInto(out *RouteGroupKind) { + *out = *in + if in.Group != nil { + in, out := &in.Group, &out.Group + *out = new(Group) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteGroupKind. +func (in *RouteGroupKind) DeepCopy() *RouteGroupKind { + if in == nil { + return nil + } + out := new(RouteGroupKind) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteNamespaces) DeepCopyInto(out *RouteNamespaces) { + *out = *in + if in.From != nil { + in, out := &in.From, &out.From + *out = new(FromNamespaces) + **out = **in + } + if in.Selector != nil { + in, out := &in.Selector, &out.Selector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteNamespaces. +func (in *RouteNamespaces) DeepCopy() *RouteNamespaces { + if in == nil { + return nil + } + out := new(RouteNamespaces) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteParentStatus) DeepCopyInto(out *RouteParentStatus) { + *out = *in + in.ParentRef.DeepCopyInto(&out.ParentRef) + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteParentStatus. +func (in *RouteParentStatus) DeepCopy() *RouteParentStatus { + if in == nil { + return nil + } + out := new(RouteParentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteStatus) DeepCopyInto(out *RouteStatus) { + *out = *in + if in.Parents != nil { + in, out := &in.Parents, &out.Parents + *out = make([]RouteParentStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteStatus. +func (in *RouteStatus) DeepCopy() *RouteStatus { + if in == nil { + return nil + } + out := new(RouteStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretObjectReference) DeepCopyInto(out *SecretObjectReference) { + *out = *in + if in.Group != nil { + in, out := &in.Group, &out.Group + *out = new(Group) + **out = **in + } + if in.Kind != nil { + in, out := &in.Kind, &out.Kind + *out = new(Kind) + **out = **in + } + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(Namespace) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretObjectReference. +func (in *SecretObjectReference) DeepCopy() *SecretObjectReference { + if in == nil { + return nil + } + out := new(SecretObjectReference) + in.DeepCopyInto(out) + return out +} diff --git a/apis/v1/zz_generated.register.go b/apis/v1/zz_generated.register.go new file mode 100644 index 0000000000..f867093084 --- /dev/null +++ b/apis/v1/zz_generated.register.go @@ -0,0 +1,71 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by register-gen. DO NOT EDIT. + +package v1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "gateway.networking.k8s.io" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Depreciated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Gateway{}, + &GatewayClass{}, + &GatewayClassList{}, + &GatewayList{}, + &HTTPRoute{}, + &HTTPRouteList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + v1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/apis/v1alpha2/gateway_types.go b/apis/v1alpha2/gateway_types.go index 9eed72d50d..bb187e8cb2 100644 --- a/apis/v1alpha2/gateway_types.go +++ b/apis/v1alpha2/gateway_types.go @@ -19,15 +19,15 @@ package v1alpha2 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" ) // +genclient // +kubebuilder:object:root=true // +kubebuilder:resource:categories=gateway-api,shortName=gtw // +kubebuilder:subresource:status -// +kubebuilder:unservedversion -// +kubebuilder:deprecatedversion:warning="The v1alpha2 version of Gateway has been deprecated and will be removed in a future release of the API. Please upgrade to v1beta1." +// +kubebuilder:skipversion +// +kubebuilder:deprecatedversion:warning="The v1alpha2 version of Gateway has been deprecated and will be removed in a future release of the API. Please upgrade to v1." // +kubebuilder:printcolumn:name="Class",type=string,JSONPath=`.spec.gatewayClassName` // +kubebuilder:printcolumn:name="Address",type=string,JSONPath=`.status.addresses[*].value` // +kubebuilder:printcolumn:name="Programmed",type=string,JSONPath=`.status.conditions[?(@.type=="Programmed")].status` @@ -35,7 +35,7 @@ import ( // Gateway represents an instance of a service-traffic handling infrastructure // by binding Listeners to a set of IP addresses. -type Gateway v1beta1.Gateway +type Gateway v1.Gateway // +kubebuilder:object:root=true @@ -53,12 +53,12 @@ type GatewayList struct { // webhook, but there are many cases that will require asynchronous // signaling via the GatewayStatus block. // +k8s:deepcopy-gen=false -type GatewaySpec = v1beta1.GatewaySpec +type GatewaySpec = v1.GatewaySpec // Listener embodies the concept of a logical endpoint where a Gateway accepts // network connections. // +k8s:deepcopy-gen=false -type Listener = v1beta1.Listener +type Listener = v1.Listener // ProtocolType defines the application protocol accepted by a Listener. // Implementations are not required to accept all the defined protocols. If an @@ -88,11 +88,11 @@ type Listener = v1beta1.Listener // +kubebuilder:validation:MaxLength=255 // +kubebuilder:validation: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]+$` // +k8s:deepcopy-gen=false -type ProtocolType = v1beta1.ProtocolType +type ProtocolType = v1.ProtocolType // GatewayTLSConfig describes a TLS configuration. // +k8s:deepcopy-gen=false -type GatewayTLSConfig = v1beta1.GatewayTLSConfig +type GatewayTLSConfig = v1.GatewayTLSConfig // TLSModeType type defines how a Gateway handles TLS sessions. // @@ -105,11 +105,11 @@ type GatewayTLSConfig = v1beta1.GatewayTLSConfig // // +kubebuilder:validation:Enum=Terminate;Passthrough // +k8s:deepcopy-gen=false -type TLSModeType = v1beta1.TLSModeType +type TLSModeType = v1.TLSModeType // AllowedRoutes defines which Routes may be attached to this Listener. // +k8s:deepcopy-gen=false -type AllowedRoutes = v1beta1.AllowedRoutes +type AllowedRoutes = v1.AllowedRoutes // FromNamespaces specifies namespace from which Routes may be attached to a // Gateway. @@ -123,46 +123,46 @@ type AllowedRoutes = v1beta1.AllowedRoutes // // +kubebuilder:validation:Enum=All;Selector;Same // +k8s:deepcopy-gen=false -type FromNamespaces = v1beta1.FromNamespaces +type FromNamespaces = v1.FromNamespaces // RouteNamespaces indicate which namespaces Routes should be selected from. // +k8s:deepcopy-gen=false -type RouteNamespaces = v1beta1.RouteNamespaces +type RouteNamespaces = v1.RouteNamespaces // RouteGroupKind indicates the group and kind of a Route resource. // +k8s:deepcopy-gen=false -type RouteGroupKind = v1beta1.RouteGroupKind +type RouteGroupKind = v1.RouteGroupKind // GatewayAddress describes an address that can be bound to a Gateway. // +k8s:deepcopy-gen=false -type GatewayAddress = v1beta1.GatewayAddress +type GatewayAddress = v1.GatewayAddress // GatewayStatus defines the observed state of Gateway. // +k8s:deepcopy-gen=false -type GatewayStatus = v1beta1.GatewayStatus +type GatewayStatus = v1.GatewayStatus // GatewayConditionType is a type of condition associated with a // Gateway. This type should be used with the GatewayStatus.Conditions // field. // +k8s:deepcopy-gen=false -type GatewayConditionType = v1beta1.GatewayConditionType +type GatewayConditionType = v1.GatewayConditionType // GatewayConditionReason defines the set of reasons that explain why a // particular Gateway condition type has been raised. // +k8s:deepcopy-gen=false -type GatewayConditionReason = v1beta1.GatewayConditionReason +type GatewayConditionReason = v1.GatewayConditionReason // ListenerStatus is the status associated with a Listener. // +k8s:deepcopy-gen=false -type ListenerStatus = v1beta1.ListenerStatus +type ListenerStatus = v1.ListenerStatus // ListenerConditionType is a type of condition associated with the // listener. This type should be used with the ListenerStatus.Conditions // field. // +k8s:deepcopy-gen=false -type ListenerConditionType = v1beta1.ListenerConditionType +type ListenerConditionType = v1.ListenerConditionType // ListenerConditionReason defines the set of reasons that explain // why a particular Listener condition type has been raised. // +k8s:deepcopy-gen=false -type ListenerConditionReason = v1beta1.ListenerConditionReason +type ListenerConditionReason = v1.ListenerConditionReason diff --git a/apis/v1alpha2/gatewayclass_types.go b/apis/v1alpha2/gatewayclass_types.go index 87d08ebffc..df6ef4b9cc 100644 --- a/apis/v1alpha2/gatewayclass_types.go +++ b/apis/v1alpha2/gatewayclass_types.go @@ -19,7 +19,7 @@ package v1alpha2 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" ) // +genclient @@ -27,8 +27,8 @@ import ( // +kubebuilder:object:root=true // +kubebuilder:resource:categories=gateway-api,scope=Cluster,shortName=gc // +kubebuilder:subresource:status -// +kubebuilder:unservedversion -// +kubebuilder:deprecatedversion:warning="The v1alpha2 version of GatewayClass has been deprecated and will be removed in a future release of the API. Please upgrade to v1beta1." +// +kubebuilder:skipversion +// +kubebuilder:deprecatedversion:warning="The v1alpha2 version of GatewayClass has been deprecated and will be removed in a future release of the API. Please upgrade to v1." // +kubebuilder:printcolumn:name="Controller",type=string,JSONPath=`.spec.controllerName` // +kubebuilder:printcolumn:name="Accepted",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].status` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` @@ -51,7 +51,7 @@ import ( // Gateway is not deleted while in use. // // GatewayClass is a Cluster level resource. -type GatewayClass v1beta1.GatewayClass +type GatewayClass v1.GatewayClass // +kubebuilder:object:root=true @@ -64,24 +64,24 @@ type GatewayClassList struct { // GatewayClassSpec reflects the configuration of a class of Gateways. // +k8s:deepcopy-gen=false -type GatewayClassSpec = v1beta1.GatewayClassSpec +type GatewayClassSpec = v1.GatewayClassSpec // ParametersReference identifies an API object containing controller-specific // configuration resource within the cluster. // +k8s:deepcopy-gen=false -type ParametersReference = v1beta1.ParametersReference +type ParametersReference = v1.ParametersReference // GatewayClassConditionType is the type for status conditions on // Gateway resources. This type should be used with the // GatewayClassStatus.Conditions field. // +k8s:deepcopy-gen=false -type GatewayClassConditionType = v1beta1.GatewayClassConditionType +type GatewayClassConditionType = v1.GatewayClassConditionType // GatewayClassConditionReason defines the set of reasons that explain why a // particular GatewayClass condition type has been raised. // +k8s:deepcopy-gen=false -type GatewayClassConditionReason = v1beta1.GatewayClassConditionReason +type GatewayClassConditionReason = v1.GatewayClassConditionReason // GatewayClassStatus is the current status for the GatewayClass. // +k8s:deepcopy-gen=false -type GatewayClassStatus = v1beta1.GatewayClassStatus +type GatewayClassStatus = v1.GatewayClassStatus diff --git a/apis/v1alpha2/grpcroute_types.go b/apis/v1alpha2/grpcroute_types.go index 7bb98e49e1..c5ae6ea2e6 100644 --- a/apis/v1alpha2/grpcroute_types.go +++ b/apis/v1alpha2/grpcroute_types.go @@ -19,7 +19,7 @@ package v1alpha2 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" ) // +genclient @@ -421,7 +421,7 @@ const ( GRPCHeaderMatchRegularExpression GRPCHeaderMatchType = "RegularExpression" ) -type GRPCHeaderName v1beta1.HeaderName +type GRPCHeaderName v1.HeaderName // GRPCRouteFilterType identifies a type of GRPCRoute filter. type GRPCRouteFilterType string diff --git a/apis/v1alpha2/httproute_types.go b/apis/v1alpha2/httproute_types.go index 20e1e32586..caf5efac0a 100644 --- a/apis/v1alpha2/httproute_types.go +++ b/apis/v1alpha2/httproute_types.go @@ -19,15 +19,15 @@ package v1alpha2 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" ) // +genclient // +kubebuilder:object:root=true // +kubebuilder:resource:categories=gateway-api // +kubebuilder:subresource:status -// +kubebuilder:unservedversion -// +kubebuilder:deprecatedversion:warning="The v1alpha2 version of HTTPRoute has been deprecated and will be removed in a future release of the API. Please upgrade to v1beta1." +// +kubebuilder:skipversion +// +kubebuilder:deprecatedversion:warning="The v1alpha2 version of HTTPRoute has been deprecated and will be removed in a future release of the API. Please upgrade to v1." // +kubebuilder:printcolumn:name="Hostnames",type=string,JSONPath=`.spec.hostnames` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` @@ -35,7 +35,7 @@ import ( // 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 v1beta1.HTTPRoute +type HTTPRoute v1.HTTPRoute // +kubebuilder:object:root=true @@ -48,13 +48,13 @@ type HTTPRouteList struct { // HTTPRouteSpec defines the desired state of HTTPRoute // +k8s:deepcopy-gen=false -type HTTPRouteSpec = v1beta1.HTTPRouteSpec +type HTTPRouteSpec = v1.HTTPRouteSpec // HTTPRouteRule defines semantics for matching an HTTP request based on // conditions (matches), processing it (filters), and forwarding the request to // an API object (backendRefs). // +k8s:deepcopy-gen=false -type HTTPRouteRule = v1beta1.HTTPRouteRule +type HTTPRouteRule = v1.HTTPRouteRule // PathMatchType specifies the semantics of how HTTP paths should be compared. // Valid PathMatchType values, along with their conformance level, are: @@ -77,11 +77,11 @@ type HTTPRouteRule = v1beta1.HTTPRouteRule // // +kubebuilder:validation:Enum=Exact;PathPrefix;RegularExpression // +k8s:deepcopy-gen=false -type PathMatchType = v1beta1.PathMatchType +type PathMatchType = v1.PathMatchType // HTTPPathMatch describes how to select a HTTP route by matching the HTTP request path. // +k8s:deepcopy-gen=false -type HTTPPathMatch = v1beta1.HTTPPathMatch +type HTTPPathMatch = v1.HTTPPathMatch // HeaderMatchType specifies the semantics of how HTTP header values should be // compared. Valid HeaderMatchType values, along with their conformance levels, are: @@ -98,7 +98,7 @@ type HTTPPathMatch = v1beta1.HTTPPathMatch // // +kubebuilder:validation:Enum=Exact;RegularExpression // +k8s:deepcopy-gen=false -type HeaderMatchType = v1beta1.HeaderMatchType +type HeaderMatchType = v1.HeaderMatchType // HTTPHeaderName is the name of an HTTP header. // @@ -113,12 +113,12 @@ type HeaderMatchType = v1beta1.HeaderMatchType // // * "/invalid" - "/" is an invalid character // +k8s:deepcopy-gen=false -type HTTPHeaderName = v1beta1.HeaderName +type HTTPHeaderName = v1.HeaderName // HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request // headers. // +k8s:deepcopy-gen=false -type HTTPHeaderMatch = v1beta1.HTTPHeaderMatch +type HTTPHeaderMatch = v1.HTTPHeaderMatch // QueryParamMatchType specifies the semantics of how HTTP query parameter // values should be compared. Valid QueryParamMatchType values, along with their @@ -136,12 +136,12 @@ type HTTPHeaderMatch = v1beta1.HTTPHeaderMatch // // +kubebuilder:validation:Enum=Exact;RegularExpression // +k8s:deepcopy-gen=false -type QueryParamMatchType = v1beta1.QueryParamMatchType +type QueryParamMatchType = v1.QueryParamMatchType // HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP // query parameters. // +k8s:deepcopy-gen=false -type HTTPQueryParamMatch = v1beta1.HTTPQueryParamMatch +type HTTPQueryParamMatch = v1.HTTPQueryParamMatch // HTTPMethod describes how to select a HTTP route by matching the HTTP // method as defined by @@ -158,7 +158,7 @@ type HTTPQueryParamMatch = v1beta1.HTTPQueryParamMatch // // +kubebuilder:validation:Enum=GET;HEAD;POST;PUT;DELETE;CONNECT;OPTIONS;TRACE;PATCH // +k8s:deepcopy-gen=false -type HTTPMethod = v1beta1.HTTPMethod +type HTTPMethod = v1.HTTPMethod // HTTPRouteMatch defines the predicate used to match requests to a given // action. Multiple match types are ANDed together, i.e. the match will @@ -178,7 +178,7 @@ type HTTPMethod = v1beta1.HTTPMethod // // ``` // +k8s:deepcopy-gen=false -type HTTPRouteMatch = v1beta1.HTTPRouteMatch +type HTTPRouteMatch = v1.HTTPRouteMatch // HTTPRouteFilter defines processing steps that must be completed during the // request or response lifecycle. HTTPRouteFilters are meant as an extension @@ -187,34 +187,38 @@ type HTTPRouteMatch = v1beta1.HTTPRouteMatch // authentication strategies, rate-limiting, and traffic shaping. API // guarantee/conformance is defined based on the type of the filter. // +k8s:deepcopy-gen=false -type HTTPRouteFilter = v1beta1.HTTPRouteFilter +type HTTPRouteFilter = v1.HTTPRouteFilter // HTTPRouteFilterType identifies a type of HTTPRoute filter. // +k8s:deepcopy-gen=false -type HTTPRouteFilterType = v1beta1.HTTPRouteFilterType +type HTTPRouteFilterType = v1.HTTPRouteFilterType + +// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute. +// +k8s:deepcopy-gen=false +type HTTPRouteTimeouts = v1.HTTPRouteTimeouts // HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. // +k8s:deepcopy-gen=false -type HTTPHeader = v1beta1.HTTPHeader +type HTTPHeader = v1.HTTPHeader // HTTPHeaderFilter defines a filter that modifies the headers of an HTTP request // or response. // +k8s:deepcopy-gen=false -type HTTPHeaderFilter = v1beta1.HTTPHeaderFilter +type HTTPHeaderFilter = v1.HTTPHeaderFilter // HTTPPathModifierType defines the type of path redirect or rewrite. // +k8s:deepcopy-gen=false -type HTTPPathModifierType = v1beta1.HTTPPathModifierType +type HTTPPathModifierType = v1.HTTPPathModifierType // HTTPPathModifier defines configuration for path modifiers. // // +k8s:deepcopy-gen=false -type HTTPPathModifier = v1beta1.HTTPPathModifier +type HTTPPathModifier = v1.HTTPPathModifier // HTTPRequestRedirect defines a filter that redirects a request. This filter // MUST NOT be used on the same Route rule as a HTTPURLRewrite filter. // +k8s:deepcopy-gen=false -type HTTPRequestRedirectFilter = v1beta1.HTTPRequestRedirectFilter +type HTTPRequestRedirectFilter = v1.HTTPRequestRedirectFilter // HTTPURLRewriteFilter defines a filter that modifies a request during // forwarding. At most one of these filters may be used on a Route rule. This @@ -224,16 +228,16 @@ type HTTPRequestRedirectFilter = v1beta1.HTTPRequestRedirectFilter // // // +k8s:deepcopy-gen=false -type HTTPURLRewriteFilter = v1beta1.HTTPURLRewriteFilter +type HTTPURLRewriteFilter = v1.HTTPURLRewriteFilter // HTTPRequestMirrorFilter defines configuration for the RequestMirror filter. // +k8s:deepcopy-gen=false -type HTTPRequestMirrorFilter = v1beta1.HTTPRequestMirrorFilter +type HTTPRequestMirrorFilter = v1.HTTPRequestMirrorFilter // HTTPBackendRef defines how a HTTPRoute should forward an HTTP request. // +k8s:deepcopy-gen=false -type HTTPBackendRef = v1beta1.HTTPBackendRef +type HTTPBackendRef = v1.HTTPBackendRef // HTTPRouteStatus defines the observed state of HTTPRoute. // +k8s:deepcopy-gen=false -type HTTPRouteStatus = v1beta1.HTTPRouteStatus +type HTTPRouteStatus = v1.HTTPRouteStatus diff --git a/apis/v1alpha2/object_reference_types.go b/apis/v1alpha2/object_reference_types.go index f2798e597b..13ae680cfe 100644 --- a/apis/v1alpha2/object_reference_types.go +++ b/apis/v1alpha2/object_reference_types.go @@ -16,7 +16,7 @@ limitations under the License. package v1alpha2 -import "sigs.k8s.io/gateway-api/apis/v1beta1" +import v1 "sigs.k8s.io/gateway-api/apis/v1" // LocalObjectReference identifies an API object within the namespace of the // referrer. @@ -27,7 +27,7 @@ import "sigs.k8s.io/gateway-api/apis/v1beta1" // be rejected by the implementation, with appropriate Conditions set // on the containing object. // +k8s:deepcopy-gen=false -type LocalObjectReference = v1beta1.LocalObjectReference +type LocalObjectReference = v1.LocalObjectReference // SecretObjectReference identifies an API object including its namespace, // defaulting to Secret. @@ -39,7 +39,7 @@ type LocalObjectReference = v1beta1.LocalObjectReference // be rejected by the implementation, with appropriate Conditions set // on the containing object. // +k8s:deepcopy-gen=false -type SecretObjectReference = v1beta1.SecretObjectReference +type SecretObjectReference = v1.SecretObjectReference // BackendObjectReference defines how an ObjectReference that is // specific to BackendRef. It includes a few additional fields and features @@ -57,4 +57,4 @@ type SecretObjectReference = v1beta1.SecretObjectReference // be rejected by the implementation, with appropriate Conditions set // on the containing object. // +k8s:deepcopy-gen=false -type BackendObjectReference = v1beta1.BackendObjectReference +type BackendObjectReference = v1.BackendObjectReference diff --git a/apis/v1alpha2/shared_types.go b/apis/v1alpha2/shared_types.go index 788fef9a06..4ff14aace6 100644 --- a/apis/v1alpha2/shared_types.go +++ b/apis/v1alpha2/shared_types.go @@ -16,9 +16,7 @@ limitations under the License. package v1alpha2 -import ( - "sigs.k8s.io/gateway-api/apis/v1beta1" -) +import v1 "sigs.k8s.io/gateway-api/apis/v1" // ParentReference 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 @@ -34,18 +32,18 @@ import ( // 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. // +k8s:deepcopy-gen=false -type ParentReference = v1beta1.ParentReference +type ParentReference = v1.ParentReference // CommonRouteSpec defines the common attributes that all Routes MUST include // within their spec. // +k8s:deepcopy-gen=false -type CommonRouteSpec = v1beta1.CommonRouteSpec +type CommonRouteSpec = v1.CommonRouteSpec // PortNumber defines a network port. // // +kubebuilder:validation:Minimum=1 // +kubebuilder:validation:Maximum=65535 -type PortNumber = v1beta1.PortNumber +type PortNumber = v1.PortNumber // BackendRef defines how a Route should forward a request to a Kubernetes // resource. @@ -55,13 +53,13 @@ type PortNumber = v1beta1.PortNumber // namespace's owner to accept the reference. See the ReferenceGrant // documentation for details. // +k8s:deepcopy-gen=false -type BackendRef = v1beta1.BackendRef +type BackendRef = v1.BackendRef // RouteConditionType is a type of condition for a route. -type RouteConditionType = v1beta1.RouteConditionType +type RouteConditionType = v1.RouteConditionType // RouteConditionReason is a reason for a route condition. -type RouteConditionReason = v1beta1.RouteConditionReason +type RouteConditionReason = v1.RouteConditionReason const ( // This condition indicates whether the route has been accepted or rejected @@ -148,12 +146,12 @@ const ( // RouteParentStatus describes the status of a route with respect to an // associated Parent. // +k8s:deepcopy-gen=false -type RouteParentStatus = v1beta1.RouteParentStatus +type RouteParentStatus = v1.RouteParentStatus // RouteStatus defines the common attributes that all Routes MUST include within // their status. // +k8s:deepcopy-gen=false -type RouteStatus = v1beta1.RouteStatus +type RouteStatus = v1.RouteStatus // Hostname is the fully qualified domain name of a network host. This matches // the RFC 1123 definition of a hostname with 2 notable exceptions: @@ -173,7 +171,7 @@ type RouteStatus = v1beta1.RouteStatus // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=`^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` -type Hostname = v1beta1.Hostname +type Hostname = v1.Hostname // PreciseHostname is the fully qualified domain name of a network host. This // matches the RFC 1123 definition of a hostname with 1 notable exception that @@ -186,7 +184,7 @@ type Hostname = v1beta1.Hostname // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` -type PreciseHostname = v1beta1.PreciseHostname +type PreciseHostname = v1.PreciseHostname // Group refers to a Kubernetes Group. It must either be an empty string or a // RFC 1123 subdomain. @@ -206,7 +204,7 @@ type PreciseHostname = v1beta1.PreciseHostname // // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=`^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` -type Group = v1beta1.Group +type Group = v1.Group // Kind refers to a Kubernetes Kind. // @@ -222,7 +220,7 @@ type Group = v1beta1.Group // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern=`^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` -type Kind = v1beta1.Kind +type Kind = v1.Kind // ObjectName refers to the name of a Kubernetes object. // Object names can have a variety of forms, including RFC1123 subdomains, @@ -230,7 +228,7 @@ type Kind = v1beta1.Kind // // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 -type ObjectName = v1beta1.ObjectName +type ObjectName = v1.ObjectName // Namespace refers to a Kubernetes namespace. It must be a RFC 1123 label. // @@ -251,7 +249,7 @@ type ObjectName = v1beta1.ObjectName // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 -type Namespace = v1beta1.Namespace +type Namespace = v1.Namespace // SectionName is the name of a section in a Kubernetes resource. // @@ -270,7 +268,7 @@ type Namespace = v1beta1.Namespace // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 -type SectionName = v1beta1.SectionName +type SectionName = v1.SectionName // GatewayController is the name of a Gateway API controller. It must be a // domain prefixed path. @@ -287,7 +285,7 @@ type SectionName = v1beta1.SectionName // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` -type GatewayController = v1beta1.GatewayController +type GatewayController = v1.GatewayController // AnnotationKey is the key of an annotation in Gateway API. This is used for // validation of maps such as TLS options. This matches the Kubernetes @@ -309,7 +307,7 @@ type GatewayController = v1beta1.GatewayController // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=`^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]/?)*$` -type AnnotationKey = v1beta1.AnnotationKey +type AnnotationKey = v1.AnnotationKey // 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 @@ -318,7 +316,7 @@ type AnnotationKey = v1beta1.AnnotationKey // // +kubebuilder:validation:MinLength=0 // +kubebuilder:validation:MaxLength=4096 -type AnnotationValue = v1beta1.AnnotationValue +type AnnotationValue = v1.AnnotationValue // AddressType defines how a network address is represented as a text string. // This may take two possible forms: @@ -338,11 +336,11 @@ type AnnotationValue = v1beta1.AnnotationValue // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=`^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` -type AddressType = v1beta1.AddressType +type AddressType = v1.AddressType // Duration is a string value representing a duration in time. The format is as specified // in GEP-2257, a strict subset of the syntax parsed by Golang time.ParseDuration. -type Duration = v1beta1.Duration +type Duration = v1.Duration const ( // A textual representation of a numeric IP address. IPv4 diff --git a/apis/v1alpha2/validation/gateway_test.go b/apis/v1alpha2/validation/gateway_test.go index e5b10b51eb..c76a403807 100644 --- a/apis/v1alpha2/validation/gateway_test.go +++ b/apis/v1alpha2/validation/gateway_test.go @@ -21,8 +21,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) func TestValidateGateway(t *testing.T) { @@ -56,7 +56,7 @@ func TestValidateGateway(t *testing.T) { mutate: func(gw *gatewayv1a2.Gateway) { hostname := gatewayv1a2.Hostname("foo.bar.com") gw.Spec.Listeners[0].Hostname = &hostname - gw.Spec.Listeners[0].Protocol = gatewayv1b1.TCPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.TCPProtocolType }, expectErrsOnFields: []string{"spec.listeners[0].hostname"}, }, @@ -64,7 +64,7 @@ func TestValidateGateway(t *testing.T) { mutate: func(gw *gatewayv1a2.Gateway) { hostname := gatewayv1a2.Hostname("foo.bar.com") gw.Spec.Listeners[0].Hostname = &hostname - gw.Spec.Listeners[0].Protocol = gatewayv1b1.UDPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.UDPProtocolType }, expectErrsOnFields: []string{"spec.listeners[0].hostname"}, }, diff --git a/apis/v1alpha2/validation/httproute_test.go b/apis/v1alpha2/validation/httproute_test.go index 159ab4f587..562988c695 100644 --- a/apis/v1alpha2/validation/httproute_test.go +++ b/apis/v1alpha2/validation/httproute_test.go @@ -23,13 +23,13 @@ import ( "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/util/validation/field" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) func TestValidateHTTPRoute(t *testing.T) { testService := gatewayv1a2.ObjectName("test-service") - pathPrefixMatchType := gatewayv1b1.PathMatchPathPrefix + pathPrefixMatchType := gatewayv1.PathMatchPathPrefix tests := []struct { name string @@ -43,7 +43,7 @@ func TestValidateHTTPRoute(t *testing.T) { Matches: []gatewayv1a2.HTTPRouteMatch{ { Path: &gatewayv1a2.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, @@ -53,7 +53,7 @@ func TestValidateHTTPRoute(t *testing.T) { BackendRef: gatewayv1a2.BackendRef{ BackendObjectReference: gatewayv1a2.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, Weight: ptrTo(int32(100)), }, @@ -69,18 +69,18 @@ func TestValidateHTTPRoute(t *testing.T) { Matches: []gatewayv1a2.HTTPRouteMatch{ { Path: &gatewayv1a2.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, }, Filters: []gatewayv1a2.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1a2.HTTPRequestMirrorFilter{ BackendRef: gatewayv1a2.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(8081)), + Port: ptrTo(gatewayv1.PortNumber(8081)), }, }, }, @@ -95,26 +95,26 @@ func TestValidateHTTPRoute(t *testing.T) { Matches: []gatewayv1a2.HTTPRouteMatch{ { Path: &gatewayv1a2.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, }, Filters: []gatewayv1a2.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, }, { - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("bar"), }, }, @@ -130,14 +130,14 @@ func TestValidateHTTPRoute(t *testing.T) { Matches: []gatewayv1a2.HTTPRouteMatch{ { Path: &gatewayv1a2.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, }, Filters: []gatewayv1a2.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1a2.HTTPHeaderFilter{ Set: []gatewayv1a2.HTTPHeader{ { @@ -148,16 +148,16 @@ func TestValidateHTTPRoute(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1a2.HTTPRequestMirrorFilter{ BackendRef: gatewayv1a2.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1a2.HTTPHeaderFilter{ Add: []gatewayv1a2.HTTPHeader{ { @@ -178,16 +178,16 @@ func TestValidateHTTPRoute(t *testing.T) { Matches: []gatewayv1a2.HTTPRouteMatch{ { Path: &gatewayv1a2.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, }, Filters: []gatewayv1a2.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterResponseHeaderModifier, - ResponseHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ - Add: []gatewayv1b1.HTTPHeader{ + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, + ResponseHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{ { Name: "extra-header", Value: "foo", @@ -196,7 +196,7 @@ func TestValidateHTTPRoute(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1a2.HTTPHeaderFilter{ Set: []gatewayv1a2.HTTPHeader{ { @@ -207,9 +207,9 @@ func TestValidateHTTPRoute(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterResponseHeaderModifier, - ResponseHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ - Set: []gatewayv1b1.HTTPHeader{ + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, + ResponseHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Set: []gatewayv1.HTTPHeader{ { Name: "other-header", Value: "bat", @@ -218,7 +218,7 @@ func TestValidateHTTPRoute(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1a2.HTTPHeaderFilter{ Add: []gatewayv1a2.HTTPHeader{ { @@ -239,14 +239,14 @@ func TestValidateHTTPRoute(t *testing.T) { Matches: []gatewayv1a2.HTTPRouteMatch{ { Path: &gatewayv1a2.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, }, Filters: []gatewayv1a2.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1a2.HTTPHeaderFilter{ Set: []gatewayv1a2.HTTPHeader{ { @@ -257,11 +257,11 @@ func TestValidateHTTPRoute(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1a2.HTTPRequestMirrorFilter{ BackendRef: gatewayv1a2.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, }, @@ -296,10 +296,10 @@ func TestValidateHTTPRoute(t *testing.T) { { Filters: []gatewayv1a2.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, RequestRedirect: &gatewayv1a2.HTTPRequestRedirectFilter{ Path: &gatewayv1a2.HTTPPathModifier{ - Type: gatewayv1b1.FullPathHTTPPathModifier, + Type: gatewayv1.FullPathHTTPPathModifier, ReplaceFullPath: ptrTo("foo"), }, }, @@ -312,10 +312,10 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 2, rules: []gatewayv1a2.HTTPRouteRule{{ Filters: []gatewayv1a2.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, RequestRedirect: &gatewayv1a2.HTTPRequestRedirectFilter{ Path: &gatewayv1a2.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplaceFullPath: ptrTo("foo"), }, }, @@ -332,10 +332,10 @@ func TestValidateHTTPRoute(t *testing.T) { }, }}, Filters: []gatewayv1a2.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{ Path: &gatewayv1a2.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -346,10 +346,10 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 1, rules: []gatewayv1a2.HTTPRouteRule{{ Filters: []gatewayv1a2.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{ Path: &gatewayv1a2.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -371,10 +371,10 @@ func TestValidateHTTPRoute(t *testing.T) { }, }}, Filters: []gatewayv1a2.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{ Path: &gatewayv1a2.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -385,10 +385,10 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 2, rules: []gatewayv1a2.HTTPRouteRule{{ Filters: []gatewayv1a2.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{ Path: &gatewayv1a2.HTTPPathModifier{ - Type: gatewayv1b1.FullPathHTTPPathModifier, + Type: gatewayv1.FullPathHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -399,18 +399,18 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 3, rules: []gatewayv1a2.HTTPRouteRule{{ Filters: []gatewayv1a2.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{ Path: &gatewayv1a2.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, RequestRedirect: &gatewayv1a2.HTTPRequestRedirectFilter{ Path: &gatewayv1a2.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -446,17 +446,17 @@ func TestValidateHTTPBackendUniqueFilters(t *testing.T) { BackendRef: gatewayv1a2.BackendRef{ BackendObjectReference: gatewayv1a2.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, Weight: ptrTo(int32(100)), }, Filters: []gatewayv1a2.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1a2.HTTPRequestMirrorFilter{ BackendRef: gatewayv1a2.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, }, @@ -473,25 +473,25 @@ func TestValidateHTTPBackendUniqueFilters(t *testing.T) { BackendRef: gatewayv1a2.BackendRef{ BackendObjectReference: gatewayv1a2.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, Filters: []gatewayv1a2.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1a2.HTTPRequestMirrorFilter{ BackendRef: gatewayv1a2.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1a2.HTTPRequestMirrorFilter{ BackendRef: gatewayv1a2.BackendObjectReference{ Name: specialService, - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, }, @@ -520,21 +520,21 @@ func TestValidateHTTPPathMatch(t *testing.T) { }{{ name: "invalid httpRoute prefix", path: &gatewayv1a2.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/."), }, errCount: 1, }, { name: "invalid httpRoute Exact", path: &gatewayv1a2.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("Exact")), + Type: ptrTo(gatewayv1.PathMatchType("Exact")), Value: ptrTo("/foo/./bar"), }, errCount: 1, }, { name: "invalid httpRoute prefix", path: &gatewayv1a2.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, errCount: 0, @@ -551,7 +551,7 @@ func TestValidateHTTPPathMatch(t *testing.T) { BackendRef: gatewayv1a2.BackendRef{ BackendObjectReference: gatewayv1a2.BackendObjectReference{ Name: gatewayv1a2.ObjectName("test"), - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, }}, @@ -612,7 +612,7 @@ func TestValidateHTTPHeaderMatches(t *testing.T) { BackendRef: gatewayv1a2.BackendRef{ BackendObjectReference: gatewayv1a2.BackendObjectReference{ Name: gatewayv1a2.ObjectName("test"), - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, }}, @@ -676,7 +676,7 @@ func TestValidateHTTPQueryParamMatches(t *testing.T) { BackendRef: gatewayv1a2.BackendRef{ BackendObjectReference: gatewayv1a2.BackendObjectReference{ Name: gatewayv1a2.ObjectName("test"), - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, }}, @@ -803,7 +803,7 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { }{{ name: "valid HTTPRouteFilterRequestHeaderModifier route filter", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1a2.HTTPHeaderFilter{ Set: []gatewayv1a2.HTTPHeader{{Name: "name"}}, Add: []gatewayv1a2.HTTPHeader{{Name: "add"}}, @@ -814,46 +814,46 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { }, { name: "invalid HTTPRouteFilterRequestHeaderModifier type filter with non-matching field", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestMirror: &gatewayv1a2.HTTPRequestMirrorFilter{}, }, errCount: 2, }, { name: "invalid HTTPRouteFilterRequestHeaderModifier type filter with empty value field", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, }, errCount: 1, }, { name: "valid HTTPRouteFilterRequestMirror route filter", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1a2.HTTPRequestMirrorFilter{BackendRef: gatewayv1a2.BackendObjectReference{ Group: new(gatewayv1a2.Group), Kind: new(gatewayv1a2.Kind), Name: "name", Namespace: new(gatewayv1a2.Namespace), - Port: ptrTo(gatewayv1b1.PortNumber(22)), + Port: ptrTo(gatewayv1.PortNumber(22)), }}, }, errCount: 0, }, { name: "invalid HTTPRouteFilterRequestMirror type filter with non-matching field", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestHeaderModifier: &gatewayv1a2.HTTPHeaderFilter{}, }, errCount: 2, }, { name: "invalid HTTPRouteFilterRequestMirror type filter with empty value field", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, }, errCount: 1, }, { name: "valid HTTPRouteFilterRequestRedirect route filter", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, RequestRedirect: &gatewayv1a2.HTTPRequestRedirectFilter{ Scheme: new(string), Hostname: new(gatewayv1a2.PreciseHostname), @@ -866,20 +866,20 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { }, { name: "invalid HTTPRouteFilterRequestRedirect type filter with non-matching field", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, RequestMirror: &gatewayv1a2.HTTPRequestMirrorFilter{}, }, errCount: 2, }, { name: "invalid HTTPRouteFilterRequestRedirect type filter with empty value field", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, }, errCount: 1, }, { name: "valid HTTPRouteFilterExtensionRef filter", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterExtensionRef, + Type: gatewayv1.HTTPRouteFilterExtensionRef, ExtensionRef: &gatewayv1a2.LocalObjectReference{ Group: "group", Kind: "kind", @@ -890,20 +890,20 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { }, { name: "invalid HTTPRouteFilterExtensionRef type filter with non-matching field", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterExtensionRef, + Type: gatewayv1.HTTPRouteFilterExtensionRef, RequestMirror: &gatewayv1a2.HTTPRequestMirrorFilter{}, }, errCount: 2, }, { name: "invalid HTTPRouteFilterExtensionRef type filter with empty value field", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterExtensionRef, + Type: gatewayv1.HTTPRouteFilterExtensionRef, }, errCount: 1, }, { name: "valid HTTPRouteFilterURLRewrite route filter", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{ Hostname: new(gatewayv1a2.PreciseHostname), Path: &gatewayv1a2.HTTPPathModifier{}, @@ -913,14 +913,14 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { }, { name: "invalid HTTPRouteFilterURLRewrite type filter with non-matching field", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, RequestMirror: &gatewayv1a2.HTTPRequestMirrorFilter{}, }, errCount: 2, }, { name: "invalid HTTPRouteFilterURLRewrite type filter with empty value field", routeFilter: gatewayv1a2.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, }, errCount: 1, }, { @@ -939,7 +939,7 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { BackendRef: gatewayv1a2.BackendRef{ BackendObjectReference: gatewayv1a2.BackendObjectReference{ Name: gatewayv1a2.ObjectName("test"), - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, }}, diff --git a/apis/v1alpha2/zz_generated.deepcopy.go b/apis/v1alpha2/zz_generated.deepcopy.go index a81c1e862d..c3486ee058 100644 --- a/apis/v1alpha2/zz_generated.deepcopy.go +++ b/apis/v1alpha2/zz_generated.deepcopy.go @@ -21,9 +21,9 @@ limitations under the License. package v1alpha2 import ( - "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/gateway-api/apis/v1beta1" + "sigs.k8s.io/gateway-api/apis/v1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -58,7 +58,7 @@ func (in *BackendTLSPolicyConfig) DeepCopyInto(out *BackendTLSPolicyConfig) { *out = *in if in.CACertRefs != nil { in, out := &in.CACertRefs, &out.CACertRefs - *out = make([]v1beta1.LocalObjectReference, len(*in)) + *out = make([]v1.LocalObjectReference, len(*in)) copy(*out, *in) } if in.WellKnownCACerts != nil { @@ -155,7 +155,7 @@ func (in *GRPCHeaderMatch) DeepCopyInto(out *GRPCHeaderMatch) { *out = *in if in.Type != nil { in, out := &in.Type, &out.Type - *out = new(v1beta1.HeaderMatchType) + *out = new(v1.HeaderMatchType) **out = **in } } @@ -232,22 +232,22 @@ func (in *GRPCRouteFilter) DeepCopyInto(out *GRPCRouteFilter) { *out = *in if in.RequestHeaderModifier != nil { in, out := &in.RequestHeaderModifier, &out.RequestHeaderModifier - *out = new(v1beta1.HTTPHeaderFilter) + *out = new(v1.HTTPHeaderFilter) (*in).DeepCopyInto(*out) } if in.ResponseHeaderModifier != nil { in, out := &in.ResponseHeaderModifier, &out.ResponseHeaderModifier - *out = new(v1beta1.HTTPHeaderFilter) + *out = new(v1.HTTPHeaderFilter) (*in).DeepCopyInto(*out) } if in.RequestMirror != nil { in, out := &in.RequestMirror, &out.RequestMirror - *out = new(v1beta1.HTTPRequestMirrorFilter) + *out = new(v1.HTTPRequestMirrorFilter) (*in).DeepCopyInto(*out) } if in.ExtensionRef != nil { in, out := &in.ExtensionRef, &out.ExtensionRef - *out = new(v1beta1.LocalObjectReference) + *out = new(v1.LocalObjectReference) **out = **in } } @@ -363,7 +363,7 @@ func (in *GRPCRouteSpec) DeepCopyInto(out *GRPCRouteSpec) { in.CommonRouteSpec.DeepCopyInto(&out.CommonRouteSpec) if in.Hostnames != nil { in, out := &in.Hostnames, &out.Hostnames - *out = make([]v1beta1.Hostname, len(*in)) + *out = make([]v1.Hostname, len(*in)) copy(*out, *in) } if in.Rules != nil { @@ -584,7 +584,7 @@ func (in *PolicyAncestorStatus) DeepCopyInto(out *PolicyAncestorStatus) { in.AncestorRef.DeepCopyInto(&out.AncestorRef) if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) + *out = make([]metav1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -628,7 +628,7 @@ func (in *PolicyTargetReference) DeepCopyInto(out *PolicyTargetReference) { *out = *in if in.Namespace != nil { in, out := &in.Namespace, &out.Namespace - *out = new(v1beta1.Namespace) + *out = new(v1.Namespace) **out = **in } } @@ -649,7 +649,7 @@ func (in *PolicyTargetReferenceWithSectionName) DeepCopyInto(out *PolicyTargetRe in.PolicyTargetReference.DeepCopyInto(&out.PolicyTargetReference) if in.SectionName != nil { in, out := &in.SectionName, &out.SectionName - *out = new(v1beta1.SectionName) + *out = new(v1.SectionName) **out = **in } } @@ -786,7 +786,7 @@ func (in *TCPRouteRule) DeepCopyInto(out *TCPRouteRule) { *out = *in if in.BackendRefs != nil { in, out := &in.BackendRefs, &out.BackendRefs - *out = make([]v1beta1.BackendRef, len(*in)) + *out = make([]v1.BackendRef, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -906,7 +906,7 @@ func (in *TLSRouteRule) DeepCopyInto(out *TLSRouteRule) { *out = *in if in.BackendRefs != nil { in, out := &in.BackendRefs, &out.BackendRefs - *out = make([]v1beta1.BackendRef, len(*in)) + *out = make([]v1.BackendRef, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -929,7 +929,7 @@ func (in *TLSRouteSpec) DeepCopyInto(out *TLSRouteSpec) { in.CommonRouteSpec.DeepCopyInto(&out.CommonRouteSpec) if in.Hostnames != nil { in, out := &in.Hostnames, &out.Hostnames - *out = make([]v1beta1.Hostname, len(*in)) + *out = make([]v1.Hostname, len(*in)) copy(*out, *in) } if in.Rules != nil { @@ -1031,7 +1031,7 @@ func (in *UDPRouteRule) DeepCopyInto(out *UDPRouteRule) { *out = *in if in.BackendRefs != nil { in, out := &in.BackendRefs, &out.BackendRefs - *out = make([]v1beta1.BackendRef, len(*in)) + *out = make([]v1.BackendRef, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } diff --git a/apis/v1beta1/gateway_types.go b/apis/v1beta1/gateway_types.go index 4882a4d244..8170166693 100644 --- a/apis/v1beta1/gateway_types.go +++ b/apis/v1beta1/gateway_types.go @@ -18,6 +18,8 @@ package v1beta1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + v1 "sigs.k8s.io/gateway-api/apis/v1" ) // +genclient @@ -32,18 +34,7 @@ import ( // Gateway represents an instance of a service-traffic handling infrastructure // by binding Listeners to a set of IP addresses. -type Gateway struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - // Spec defines the desired state of Gateway. - Spec GatewaySpec `json:"spec"` - - // Status defines the current state of Gateway. - // - // +kubebuilder:default={conditions: {{type: "Accepted", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type: "Programmed", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}} - Status GatewayStatus `json:"status,omitempty"` -} +type Gateway v1.Gateway // +kubebuilder:object:root=true @@ -60,270 +51,13 @@ type GatewayList struct { // valid. Some invalid configurations can be caught synchronously via a // webhook, but there are many cases that will require asynchronous // signaling via the GatewayStatus block. -type GatewaySpec struct { - // GatewayClassName used for this Gateway. This is the name of a - // GatewayClass resource. - GatewayClassName ObjectName `json:"gatewayClassName"` - - // Listeners associated with this Gateway. Listeners define - // logical endpoints that are bound on this Gateway's addresses. - // At least one Listener MUST be specified. - // - // Each Listener in a set of Listeners (for example, in a single Gateway) - // MUST be _distinct_, in that a traffic flow MUST be able to be assigned to - // exactly one listener. (This section uses "set of Listeners" rather than - // "Listeners in a single Gateway" because implementations MAY merge configuration - // from multiple Gateways onto a single data plane, and these rules _also_ - // apply in that case). - // - // Practically, this means that each listener in a set MUST have a unique - // combination of Port, Protocol, and, if supported by the protocol, Hostname. - // - // Some combinations of port, protocol, and TLS settings are considered - // Core support and MUST be supported by implementations based on their - // targeted conformance profile: - // - // HTTP Profile - // - // 1. HTTPRoute, Port: 80, Protocol: HTTP - // 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: Terminate, TLS keypair provided - // - // TLS Profile - // - // 1. TLSRoute, Port: 443, Protocol: TLS, TLS Mode: Passthrough - // - // "Distinct" Listeners have the following property: - // - // The implementation can match inbound requests to a single distinct - // Listener. When multiple Listeners share values for fields (for - // example, two Listeners with the same Port value), the implementation - // can match requests to only one of the Listeners using other - // Listener fields. - // - // For example, the following Listener scenarios are distinct: - // - // 1. Multiple Listeners with the same Port that all use the "HTTP" - // Protocol that all have unique Hostname values. - // 2. Multiple Listeners with the same Port that use either the "HTTPS" or - // "TLS" Protocol that all have unique Hostname values. - // 3. A mixture of "TCP" and "UDP" Protocol Listeners, where no Listener - // with the same Protocol has the same Port value. - // - // Some fields in the Listener struct have possible values that affect - // whether the Listener is distinct. Hostname is particularly relevant - // for HTTP or HTTPS protocols. - // - // When using the Hostname value to select between same-Port, same-Protocol - // Listeners, the Hostname value must be different on each Listener for the - // Listener to be distinct. - // - // When the Listeners are distinct based on Hostname, inbound request - // hostnames MUST match from the most specific to least specific Hostname - // values to choose the correct Listener and its associated set of Routes. - // - // Exact matches must be processed before wildcard matches, and wildcard - // matches must be processed before fallback (empty Hostname value) - // matches. For example, `"foo.example.com"` takes precedence over - // `"*.example.com"`, and `"*.example.com"` takes precedence over `""`. - // - // Additionally, if there are multiple wildcard entries, more specific - // wildcard entries must be processed before less specific wildcard entries. - // For example, `"*.foo.example.com"` takes precedence over `"*.example.com"`. - // The precise definition here is that the higher the number of dots in the - // hostname to the right of the wildcard character, the higher the precedence. - // - // The wildcard character will match any number of characters _and dots_ to - // the left, however, so `"*.example.com"` will match both - // `"foo.bar.example.com"` _and_ `"bar.example.com"`. - // - // If a set of Listeners contains Listeners that are not distinct, then those - // Listeners are Conflicted, and the implementation MUST set the "Conflicted" - // condition in the Listener Status to "True". - // - // Implementations MAY choose to accept a Gateway with some Conflicted - // Listeners only if they only accept the partial Listener set that contains - // no Conflicted Listeners. To put this another way, implementations may - // accept a partial Listener set only if they throw out *all* the conflicting - // Listeners. No picking one of the conflicting listeners as the winner. - // This also means that the Gateway must have at least one non-conflicting - // Listener in this case, otherwise it violates the requirement that at - // least one Listener must be present. - // - // The implementation MUST set a "ListenersNotValid" condition on the - // Gateway Status when the Gateway contains Conflicted Listeners whether or - // not they accept the Gateway. That Condition SHOULD clearly - // indicate in the Message which Listeners are conflicted, and which are - // Accepted. Additionally, the Listener status for those listeners SHOULD - // indicate which Listeners are conflicted and not Accepted. - // - // A Gateway's Listeners are considered "compatible" if: - // - // 1. They are distinct. - // 2. The implementation can serve them in compliance with the Addresses - // requirement that all Listeners are available on all assigned - // addresses. - // - // Compatible combinations in Extended support are expected to vary across - // implementations. A combination that is compatible for one implementation - // may not be compatible for another. - // - // For example, an implementation that cannot serve both TCP and UDP listeners - // on the same address, or cannot mix HTTPS and generic TLS listens on the same port - // would not consider those cases compatible, even though they are distinct. - // - // Note that requests SHOULD match at most one Listener. For example, if - // Listeners are defined for "foo.example.com" and "*.example.com", a - // request to "foo.example.com" SHOULD only be routed using routes attached - // to the "foo.example.com" Listener (and not the "*.example.com" Listener). - // This concept is known as "Listener Isolation". Implementations that do - // not support Listener Isolation MUST clearly document this. - // - // Implementations MAY merge separate Gateways onto a single set of - // Addresses if all Listeners across all Gateways are compatible. - // - // Support: Core - // - // +listType=map - // +listMapKey=name - // +kubebuilder:validation:MinItems=1 - // +kubebuilder:validation:MaxItems=64 - // +kubebuilder:validation:XValidation:message="tls must be specified for protocols ['HTTPS', 'TLS']",rule="self.all(l, l.protocol in ['HTTPS', 'TLS'] ? has(l.tls) : true)" - // +kubebuilder:validation:XValidation:message="tls must not be specified for protocols ['HTTP', 'TCP', 'UDP']",rule="self.all(l, l.protocol in ['HTTP', 'TCP', 'UDP'] ? !has(l.tls) : true)" - // +kubebuilder:validation:XValidation:message="hostname must not be specified for protocols ['TCP', 'UDP']",rule="self.all(l, l.protocol in ['TCP', 'UDP'] ? (!has(l.hostname) || l.hostname == '') : true)" - // +kubebuilder:validation:XValidation:message="Listener name must be unique within the Gateway",rule="self.all(l1, self.exists_one(l2, l1.name == l2.name))" - // +kubebuilder:validation:XValidation:message="Combination of port, protocol and hostname must be unique for each listener",rule="self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))" - Listeners []Listener `json:"listeners"` - - // 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. - // - // 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. - // - // If no Addresses are specified, the implementation MAY schedule the - // Gateway in an implementation-specific manner, assigning an appropriate - // set of Addresses. - // - // The implementation MUST bind all Listeners to every GatewayAddress that - // it assigns to the Gateway and add a corresponding entry in - // GatewayStatus.Addresses. - // - // Support: Extended - // - // +optional - // - // +kubebuilder:validation:MaxItems=16 - // +kubebuilder:validation:XValidation:message="IPAddress values must be unique",rule="self.all(a1, a1.type == 'IPAddress' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )" - // +kubebuilder:validation:XValidation:message="Hostname values must be unique",rule="self.all(a1, a1.type == 'Hostname' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )" - Addresses []GatewayAddress `json:"addresses,omitempty"` - - // Infrastructure defines infrastructure level attributes about this Gateway instance. - // - // Support: Core - // - // - // +optional - Infrastructure GatewayInfrastructure `json:"infrastructure,omitempty"` -} +// +k8s:deepcopy-gen=false +type GatewaySpec = v1.GatewaySpec // Listener embodies the concept of a logical endpoint where a Gateway accepts // network connections. -type Listener struct { - // Name is the name of the Listener. This name MUST be unique within a - // Gateway. - // - // Support: Core - Name SectionName `json:"name"` - - // 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. - // - // 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 - // accepted. For more information, refer to the Route specific Hostnames - // documentation. - // - // Hostnames that are prefixed with a wildcard label (`*.`) are interpreted - // as a suffix match. That means that a match for `*.example.com` would match - // both `test.example.com`, and `foo.test.example.com`, but not `example.com`. - // - // Support: Core - // - // +optional - Hostname *Hostname `json:"hostname,omitempty"` - - // Port is the network port. Multiple listeners may use the - // same port, subject to the Listener compatibility rules. - // - // Support: Core - Port PortNumber `json:"port"` - - // Protocol specifies the network protocol this listener expects to receive. - // - // Support: Core - Protocol ProtocolType `json:"protocol"` - - // 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". - // - // The association of SNIs to Certificate defined in GatewayTLSConfig is - // defined based on the Hostname field for this listener. - // - // The GatewayClass MUST use the longest matching SNI out of all - // available certificates for any TLS handshake. - // - // Support: Core - // - // +optional - TLS *GatewayTLSConfig `json:"tls,omitempty"` - - // AllowedRoutes defines the types of routes that MAY be attached to a - // Listener and the trusted namespaces where those Route resources MAY be - // present. - // - // 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: - // - // * 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. - // - // 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. - // - // Support: Core - // +kubebuilder:default={namespaces:{from: Same}} - // +optional - AllowedRoutes *AllowedRoutes `json:"allowedRoutes,omitempty"` -} +// +k8s:deepcopy-gen=false +type Listener = v1.Listener // ProtocolType defines the application protocol accepted by a Listener. // Implementations are not required to accept all the defined protocols. If an @@ -337,7 +71,7 @@ type Listener struct { // exist. Such definitions must use prefixed name, such as // `mycompany.com/my-custom-protocol`. Un-prefixed names are reserved for core // protocols. Any protocol defined by implementations will fall under -// Implementation-specific conformance. +// implementation-specific conformance. // // Valid values include: // @@ -352,728 +86,82 @@ type Listener struct { // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=255 // +kubebuilder:validation: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 ProtocolType string - -const ( - // Accepts cleartext HTTP/1.1 sessions over TCP. Implementations MAY also - // support HTTP/2 over cleartext. If implementations support HTTP/2 over - // cleartext on "HTTP" listeners, that MUST be clearly documented by the - // implementation. - HTTPProtocolType ProtocolType = "HTTP" - - // Accepts HTTP/1.1 or HTTP/2 sessions over TLS. - HTTPSProtocolType ProtocolType = "HTTPS" - - // Accepts TLS sessions over TCP. - TLSProtocolType ProtocolType = "TLS" - - // Accepts TCP sessions. - TCPProtocolType ProtocolType = "TCP" - - // Accepts UDP packets. - UDPProtocolType ProtocolType = "UDP" -) +// +k8s:deepcopy-gen=false +type ProtocolType = v1.ProtocolType // GatewayTLSConfig describes a TLS configuration. -// -// +kubebuilder:validation:XValidation:message="certificateRefs must be specified when TLSModeType is Terminate",rule="self.mode == 'Terminate' ? size(self.certificateRefs) > 0 : true" -type GatewayTLSConfig struct { - // 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 - // 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. - // - // Support: Core - // - // +optional - // +kubebuilder:default=Terminate - Mode *TLSModeType `json:"mode,omitempty"` - - // 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. - // - // 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. - // - // References to a resource in different namespace are invalid UNLESS there - // is a ReferenceGrant in the target namespace that allows the certificate - // to be attached. If a ReferenceGrant does not allow this reference, the - // "ResolvedRefs" condition MUST be set to False for this listener with the - // "RefNotPermitted" reason. - // - // This field is required to have at least one element when the mode is set - // to "Terminate" (default) and is optional otherwise. - // - // CertificateRefs can reference to standard Kubernetes resources, i.e. - // Secret, or implementation-specific custom resources. - // - // Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls - // - // Support: Implementation-specific (More than one reference or other resource types) - // - // +optional - // +kubebuilder:validation:MaxItems=64 - CertificateRefs []SecretObjectReference `json:"certificateRefs,omitempty"` - - // 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. - // - // 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. - // - // Support: Implementation-specific - // - // +optional - // +kubebuilder:validation:MaxProperties=16 - Options map[AnnotationKey]AnnotationValue `json:"options,omitempty"` -} +// +k8s:deepcopy-gen=false +type GatewayTLSConfig = v1.GatewayTLSConfig // TLSModeType type defines how a Gateway handles TLS sessions. // +// Note that values may be added to this enum, implementations +// must ensure that unknown values will not cause a crash. +// +// Unknown values here must result in the implementation setting the +// Ready Condition for the Listener to `status: False`, with a +// Reason of `Invalid`. +// // +kubebuilder:validation:Enum=Terminate;Passthrough -type TLSModeType string - -const ( - // In this mode, TLS session between the downstream client - // and the Gateway is terminated at the Gateway. - TLSModeTerminate TLSModeType = "Terminate" - - // In this mode, 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. - // - // Note that SSL passthrough is only supported by TLSRoute. - TLSModePassthrough TLSModeType = "Passthrough" -) +// +k8s:deepcopy-gen=false +type TLSModeType = v1.TLSModeType // AllowedRoutes defines which Routes may be attached to this Listener. -type AllowedRoutes struct { - // Namespaces indicates namespaces from which Routes may be attached to this - // Listener. This is restricted to the namespace of this Gateway by default. - // - // Support: Core - // - // +optional - // +kubebuilder:default={from: Same} - Namespaces *RouteNamespaces `json:"namespaces,omitempty"` - - // 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. - // - // 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 - // "InvalidRouteKinds" reason. - // - // Support: Core - // - // +optional - // +kubebuilder:validation:MaxItems=8 - Kinds []RouteGroupKind `json:"kinds,omitempty"` -} +// +k8s:deepcopy-gen=false +type AllowedRoutes = v1.AllowedRoutes // FromNamespaces specifies namespace from which Routes may be attached to a // Gateway. // +// Note that values may be added to this enum, implementations +// must ensure that unknown values will not cause a crash. +// +// Unknown values here must result in the implementation setting the +// Ready Condition for the Listener to `status: False`, with a +// Reason of `Invalid`. +// // +kubebuilder:validation:Enum=All;Selector;Same -type FromNamespaces string - -const ( - // Routes in all namespaces may be attached to this Gateway. - NamespacesFromAll FromNamespaces = "All" - // Only Routes in namespaces selected by the selector may be attached to - // this Gateway. - NamespacesFromSelector FromNamespaces = "Selector" - // Only Routes in the same namespace as the Gateway may be attached to this - // Gateway. - NamespacesFromSame FromNamespaces = "Same" -) +// +k8s:deepcopy-gen=false +type FromNamespaces = v1.FromNamespaces // RouteNamespaces indicate which namespaces Routes should be selected from. -type RouteNamespaces struct { - // 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. - // - // Support: Core - // - // +optional - // +kubebuilder:default=Same - From *FromNamespaces `json:"from,omitempty"` - - // 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". - // - // Support: Core - // - // +optional - Selector *metav1.LabelSelector `json:"selector,omitempty"` -} +// +k8s:deepcopy-gen=false +type RouteNamespaces = v1.RouteNamespaces // RouteGroupKind indicates the group and kind of a Route resource. -type RouteGroupKind struct { - // Group is the group of the Route. - // - // +optional - // +kubebuilder:default=gateway.networking.k8s.io - Group *Group `json:"group,omitempty"` - - // Kind is the kind of the Route. - Kind Kind `json:"kind"` -} +// +k8s:deepcopy-gen=false +type RouteGroupKind = v1.RouteGroupKind // GatewayAddress describes an address that can be bound to a Gateway. -// -// +kubebuilder:validation:XValidation:message="Hostname value must only contain valid characters (matching ^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$)",rule="self.type == 'Hostname' ? self.value.matches(r\"\"\"^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$\"\"\"): true" -type GatewayAddress struct { - // Type of the address. - // - // +optional - // +kubebuilder:default=IPAddress - Type *AddressType `json:"type,omitempty"` - - // Value of the address. The validity of the values will depend - // on the type and support by the controller. - // - // Examples: `1.2.3.4`, `128::1`, `my-ip-address`. - // - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:MaxLength=253 - Value string `json:"value"` -} - -// GatewayStatusAddress describes a network address that is bound to a Gateway. -// -// +kubebuilder:validation:XValidation:message="Hostname value must only contain valid characters (matching ^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$)",rule="self.type == 'Hostname' ? self.value.matches(r\"\"\"^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$\"\"\"): true" -type GatewayStatusAddress struct { - // Type of the address. - // - // +optional - // +kubebuilder:default=IPAddress - Type *AddressType `json:"type,omitempty"` - - // Value of the address. The validity of the values will depend - // on the type and support by the controller. - // - // Examples: `1.2.3.4`, `128::1`, `my-ip-address`. - // - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:MaxLength=253 - Value string `json:"value"` -} +// +k8s:deepcopy-gen=false +type GatewayAddress = v1.GatewayAddress // GatewayStatus defines the observed state of Gateway. -type GatewayStatus struct { - // Addresses lists the network addresses that have been bound to the - // Gateway. - // - // This list may differ from the addresses provided in the spec under some - // conditions: - // - // * no addresses are specified, all addresses are dynamically assigned - // * a combination of specified and dynamic addresses are assigned - // * a specified address was unusable (e.g. already in use) - // - // +optional - // - // +kubebuilder:validation:MaxItems=16 - Addresses []GatewayStatusAddress `json:"addresses,omitempty"` - - // Conditions describe the current conditions of the Gateway. - // - // 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. - // - // Known condition types are: - // - // * "Accepted" - // * "Programmed" - // * "Ready" - // - // +optional - // +listType=map - // +listMapKey=type - // +kubebuilder:validation:MaxItems=8 - // +kubebuilder:default={{type: "Accepted", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type: "Programmed", status: "Unknown", reason:"Pending", 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. - // - // +optional - // +listType=map - // +listMapKey=name - // +kubebuilder:validation:MaxItems=64 - Listeners []ListenerStatus `json:"listeners,omitempty"` -} - -// GatewayInfrastructure defines infrastructure level attributes about a Gateway instance. -type GatewayInfrastructure struct { - // Labels that SHOULD be applied to any resources created in response to this Gateway. - // - // For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources. - // For other implementations, this refers to any relevant (implementation specific) "labels" concepts. - // - // An implementation may chose to add additional implementation-specific labels as they see fit. - // - // Support: Extended - // +kubebuilder:validation:MaxProperties=8 - Labels map[AnnotationKey]AnnotationValue `json:"labels,omitempty"` - - // Annotations that SHOULD be applied to any resources created in response to this Gateway. - // - // For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources. - // For other implementations, this refers to any relevant (implementation specific) "annotations" concepts. - // - // An implementation may chose to add additional implementation-specific annotations as they see fit. - // - // Support: Extended - // +kubebuilder:validation:MaxProperties=8 - Annotations map[AnnotationKey]AnnotationValue `json:"annotations,omitempty"` -} +// +k8s:deepcopy-gen=false +type GatewayStatus = v1.GatewayStatus // GatewayConditionType is a type of condition associated with a // Gateway. This type should be used with the GatewayStatus.Conditions // field. -type GatewayConditionType string +// +k8s:deepcopy-gen=false +type GatewayConditionType = v1.GatewayConditionType // GatewayConditionReason defines the set of reasons that explain why a // particular Gateway condition type has been raised. -type GatewayConditionReason string - -const ( - // This condition indicates whether a Gateway has generated some - // configuration that is assumed to be ready soon in the underlying data - // plane. - // - // It is a positive-polarity summary condition, and so should always be - // present on the resource with ObservedGeneration set. - // - // It should be set to Unknown if the controller performs updates to the - // status before it has all the information it needs to be able to determine - // if the condition is true. - // - // Possible reasons for this condition to be True are: - // - // * "Programmed" - // - // Possible reasons for this condition to be False are: - // - // * "Invalid" - // * "Pending" - // * "NoResources" - // * "AddressNotAssigned" - // - // Possible reasons for this condition to be Unknown are: - // - // * "Pending" - // - // Controllers may raise this condition with other reasons, - // but should prefer to use the reasons listed above to improve - // interoperability. - GatewayConditionProgrammed GatewayConditionType = "Programmed" - - // This reason is used with the "Programmed" condition when the condition is - // true. - GatewayReasonProgrammed GatewayConditionReason = "Programmed" - - // This reason is used with the "Programmed" and "Accepted" conditions when the Gateway is - // syntactically or semantically invalid. - GatewayReasonInvalid GatewayConditionReason = "Invalid" - - // This reason is used with the "Programmed" condition when the - // Gateway is not scheduled because insufficient infrastructure - // resources are available. - GatewayReasonNoResources GatewayConditionReason = "NoResources" - - // This reason is used with the "Programmed" condition when the underlying - // implementation and network have yet to dynamically assign addresses for a - // Gateway. - // - // Some example situations where this reason can be used: - // - // * IPAM address exhaustion - // * Address not yet allocated - // - // When this reason is used the implementation SHOULD provide a clear - // message explaining the underlying problem, ideally with some hints as to - // what actions can be taken that might resolve the problem. - GatewayReasonAddressNotAssigned GatewayConditionReason = "AddressNotAssigned" - - // This reason is used with the "Programmed" condition when the underlying - // implementation (and possibly, network) are unable to use an address that - // was provided in the Gateway specification. - // - // Some example situations where this reason can be used: - // - // * a named address not being found - // * a provided static address can't be used - // * the address is already in use - // - // When this reason is used the implementation SHOULD provide prescriptive - // information on which address is causing the problem and how to resolve it - // in the condition message. - GatewayReasonAddressNotUsable GatewayConditionReason = "AddressNotUsable" -) - -const ( - // This condition is true when the controller managing the Gateway is - // syntactically and semantically valid enough to produce some configuration - // in the underlying data plane. This does not indicate whether or not the - // configuration has been propagated to the data plane. - // - // Possible reasons for this condition to be True are: - // - // * "Accepted" - // * "ListenersNotValid" - // - // Possible reasons for this condition to be False are: - // - // * "Invalid" - // * "NotReconciled" - // * "UnsupportedAddress" - // * "ListenersNotValid" - // - // Possible reasons for this condition to be Unknown are: - // - // * "Pending" - // - // Controllers may raise this condition with other reasons, - // but should prefer to use the reasons listed above to improve - // interoperability. - GatewayConditionAccepted GatewayConditionType = "Accepted" - - // This reason is used with the "Accepted" condition when the condition is - // True. - GatewayReasonAccepted GatewayConditionReason = "Accepted" - - // This reason is used with the "Accepted" condition when one or - // more Listeners have an invalid or unsupported configuration - // and cannot be configured on the Gateway. - // This can be the reason when "Accepted" is "True" or "False", depending on whether - // the listener being invalid causes the entire Gateway to not be accepted. - GatewayReasonListenersNotValid GatewayConditionReason = "ListenersNotValid" - - // This reason is used with the "Accepted" and "Programmed" - // conditions when the status is "Unknown" and no controller has reconciled - // the Gateway. - GatewayReasonPending GatewayConditionReason = "Pending" - - // This reason is used with the "Accepted" condition to indicate that the - // Gateway could not be accepted because an address that was provided is a - // type which is not supported by the implementation. - GatewayReasonUnsupportedAddress GatewayConditionReason = "UnsupportedAddress" -) - -const ( - // Deprecated: use "Accepted" instead. - GatewayConditionScheduled GatewayConditionType = "Scheduled" - - // This reason is used with the "Scheduled" condition when the condition is - // True. - // - // Deprecated: use the "Accepted" condition with reason "Accepted" instead. - GatewayReasonScheduled GatewayConditionReason = "Scheduled" - - // Deprecated: Use "Pending" instead. - GatewayReasonNotReconciled GatewayConditionReason = "NotReconciled" -) - -const ( - // "Ready" is a condition type reserved for future use. It should not be used by implementations. - // - // If used in the future, "Ready" will represent the final state where all configuration is confirmed good - // _and has completely propagated to the data plane_. That is, it is a _guarantee_ that, as soon as something - // sees the Condition as `true`, then connections will be correctly routed _immediately_. - // - // This is a very strong guarantee, and to date no implementation has satisfied it enough to implement it. - // This reservation can be discussed in the future if necessary. - // - // Note: This condition is not really "deprecated", but rather "reserved"; however, deprecated triggers Go linters - // to alert about usage. - // Deprecated: Ready is reserved for future use - GatewayConditionReady GatewayConditionType = "Ready" - - // Deprecated: Ready is reserved for future use - GatewayReasonReady GatewayConditionReason = "Ready" - - // Deprecated: Ready is reserved for future use - GatewayReasonListenersNotReady GatewayConditionReason = "ListenersNotReady" -) +// +k8s:deepcopy-gen=false +type GatewayConditionReason = v1.GatewayConditionReason // ListenerStatus is the status associated with a Listener. -type ListenerStatus struct { - // Name is the name of the Listener that this status corresponds to. - Name SectionName `json:"name"` - - // SupportedKinds is the list indicating the Kinds supported by this - // 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"` - - // AttachedRoutes represents the total number of Routes that have been - // successfully attached to this Listener. - // - // Successful attachment of a Route to a Listener is based solely on the - // combination of the AllowedRoutes field on the corresponding Listener - // and the Route's ParentRefs field. A Route is successfully attached to - // a Listener when it is selected by the Listener's AllowedRoutes field - // AND the Route has a valid ParentRef selecting the whole Gateway - // resource or a specific Listener as a parent resource (more detail on - // attachment semantics can be found in the documentation on the various - // Route kinds ParentRefs fields). Listener or Route status does not impact - // successful attachment, i.e. the AttachedRoutes field count MUST be set - // for Listeners with condition Accepted: false and MUST count successfully - // attached Routes that may themselves have Accepted: false conditions. - // - // Uses for this field include troubleshooting Route attachment and - // measuring blast radius/impact of changes to a Listener. - AttachedRoutes int32 `json:"attachedRoutes"` - - // Conditions describe the current condition of this listener. - // - // +listType=map - // +listMapKey=type - // +kubebuilder:validation:MaxItems=8 - Conditions []metav1.Condition `json:"conditions"` -} +// +k8s:deepcopy-gen=false +type ListenerStatus = v1.ListenerStatus // ListenerConditionType is a type of condition associated with the // listener. This type should be used with the ListenerStatus.Conditions // field. -type ListenerConditionType string +// +k8s:deepcopy-gen=false +type ListenerConditionType = v1.ListenerConditionType // ListenerConditionReason defines the set of reasons that explain // why a particular Listener condition type has been raised. -type ListenerConditionReason string - -const ( - // This condition indicates that the controller was unable to resolve - // conflicting specification requirements for this Listener. If a - // Listener is conflicted, its network port should not be configured - // on any network elements. - // - // Possible reasons for this condition to be true are: - // - // * "HostnameConflict" - // * "ProtocolConflict" - // - // Possible reasons for this condition to be False are: - // - // * "NoConflicts" - // - // Controllers may raise this condition with other reasons, - // but should prefer to use the reasons listed above to improve - // interoperability. - ListenerConditionConflicted ListenerConditionType = "Conflicted" - - // This reason is used with the "Conflicted" condition when - // the Listener conflicts with hostnames in other Listeners. For - // example, this reason would be used when multiple Listeners on - // the same port use `example.com` in the hostname field. - ListenerReasonHostnameConflict ListenerConditionReason = "HostnameConflict" - - // This reason is used with the "Conflicted" condition when - // multiple Listeners are specified with the same Listener port - // number, but have conflicting protocol specifications. - ListenerReasonProtocolConflict ListenerConditionReason = "ProtocolConflict" - - // This reason is used with the "Conflicted" condition when the condition - // is False. - ListenerReasonNoConflicts ListenerConditionReason = "NoConflicts" -) - -const ( - // This condition indicates that the listener is syntactically and - // semantically valid, and that all features used in the listener's spec are - // supported. - // - // In general, a Listener will be marked as Accepted when the supplied - // configuration will generate at least some data plane configuration. - // - // For example, a Listener with an unsupported protocol will never generate - // any data plane config, and so will have Accepted set to `false.` - // Conversely, a Listener that does not have any Routes will be able to - // generate data plane config, and so will have Accepted set to `true`. - // - // Possible reasons for this condition to be True are: - // - // * "Accepted" - // - // Possible reasons for this condition to be False are: - // - // * "PortUnavailable" - // * "UnsupportedProtocol" - // - // Possible reasons for this condition to be Unknown are: - // - // * "Pending" - // - // Controllers may raise this condition with other reasons, - // but should prefer to use the reasons listed above to improve - // interoperability. - ListenerConditionAccepted ListenerConditionType = "Accepted" - - // Deprecated: use "Accepted" instead. - ListenerConditionDetached ListenerConditionType = "Detached" - - // This reason is used with the "Accepted" condition when the condition is - // True. - ListenerReasonAccepted ListenerConditionReason = "Accepted" - - // This reason is used with the "Detached" condition when the condition is - // False. - // - // Deprecated: use the "Accepted" condition with reason "Accepted" instead. - ListenerReasonAttached ListenerConditionReason = "Attached" - - // This reason is used with the "Accepted" 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 "Accepted" condition when the - // Listener could not be attached to be Gateway because its - // protocol type is not supported. - ListenerReasonUnsupportedProtocol ListenerConditionReason = "UnsupportedProtocol" -) - -const ( - // This condition indicates whether the controller was able to - // resolve all the object references for the Listener. - // - // Possible reasons for this condition to be true are: - // - // * "ResolvedRefs" - // - // Possible reasons for this condition to be False are: - // - // * "InvalidCertificateRef" - // * "InvalidRouteKinds" - // * "RefNotPermitted" - // - // Controllers may raise this condition with other reasons, - // but should prefer to use the reasons listed above to improve - // interoperability. - ListenerConditionResolvedRefs ListenerConditionType = "ResolvedRefs" - - // This reason is used with the "ResolvedRefs" condition when the condition - // is true. - ListenerReasonResolvedRefs ListenerConditionReason = "ResolvedRefs" - - // This reason is used with the "ResolvedRefs" condition when the - // Listener has a TLS configuration with at least one TLS CertificateRef - // that is invalid or does not exist. - // A CertificateRef is considered invalid when it refers to a nonexistent - // or unsupported resource or kind, or when the data within that resource - // is malformed. - // This reason must be used only when the reference is allowed, either by - // referencing an object in the same namespace as the Gateway, or when - // a cross-namespace reference has been explicitly allowed by a ReferenceGrant. - // If the reference is not allowed, the reason RefNotPermitted must be used - // instead. - ListenerReasonInvalidCertificateRef ListenerConditionReason = "InvalidCertificateRef" - - // This reason is used with the "ResolvedRefs" condition when an invalid or - // unsupported Route kind is specified by the Listener. - ListenerReasonInvalidRouteKinds ListenerConditionReason = "InvalidRouteKinds" - - // This reason is used with the "ResolvedRefs" condition when the - // Listener has a TLS configuration that references an object in another - // namespace, where the object in the other namespace does not have a - // ReferenceGrant explicitly allowing the reference. - ListenerReasonRefNotPermitted ListenerConditionReason = "RefNotPermitted" -) - -const ( - // This condition indicates whether a Listener has generated some - // configuration that will soon be ready in the underlying data plane. - // - // It is a positive-polarity summary condition, and so should always be - // present on the resource with ObservedGeneration set. - // - // It should be set to Unknown if the controller performs updates to the - // status before it has all the information it needs to be able to determine - // if the condition is true. - // - // Possible reasons for this condition to be True are: - // - // * "Programmed" - // - // Possible reasons for this condition to be False are: - // - // * "Invalid" - // * "Pending" - // - // Possible reasons for this condition to be Unknown are: - // - // * "Pending" - // - // Controllers may raise this condition with other reasons, - // but should prefer to use the reasons listed above to improve - // interoperability. - ListenerConditionProgrammed ListenerConditionType = "Programmed" - - // This reason is used with the "Programmed" condition when the condition is - // true. - ListenerReasonProgrammed ListenerConditionReason = "Programmed" - - // This reason is used with the "Ready" and "Programmed" conditions when the - // Listener is syntactically or semantically invalid. - ListenerReasonInvalid ListenerConditionReason = "Invalid" - - // This reason is used with the "Accepted", "Ready" and "Programmed" - // conditions when the Listener is either not yet reconciled or not yet not - // online and ready to accept client traffic. - ListenerReasonPending ListenerConditionReason = "Pending" -) - -const ( - // "Ready" is a condition type reserved for future use. It should not be used by implementations. - // Note: This condition is not really "deprecated", but rather "reserved"; however, deprecated triggers Go linters - // to alert about usage. - // - // If used in the future, "Ready" will represent the final state where all configuration is confirmed good - // _and has completely propagated to the data plane_. That is, it is a _guarantee_ that, as soon as something - // sees the Condition as `true`, then connections will be correctly routed _immediately_. - // - // This is a very strong guarantee, and to date no implementation has satisfied it enough to implement it. - // This reservation can be discussed in the future if necessary. - // - // Deprecated: Ready is reserved for future use - ListenerConditionReady ListenerConditionType = "Ready" - - // Deprecated: Ready is reserved for future use - ListenerReasonReady ListenerConditionReason = "Ready" -) +// +k8s:deepcopy-gen=false +type ListenerConditionReason = v1.ListenerConditionReason diff --git a/apis/v1beta1/gatewayclass_types.go b/apis/v1beta1/gatewayclass_types.go index 19f4b2154e..f1b7ed8ae4 100644 --- a/apis/v1beta1/gatewayclass_types.go +++ b/apis/v1beta1/gatewayclass_types.go @@ -18,6 +18,8 @@ package v1beta1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + v1 "sigs.k8s.io/gateway-api/apis/v1" ) // +genclient @@ -48,222 +50,37 @@ import ( // Gateway is not deleted while in use. // // GatewayClass is a Cluster level resource. -type GatewayClass struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` +type GatewayClass v1.GatewayClass - // Spec defines the desired state of GatewayClass. - Spec GatewayClassSpec `json:"spec"` +// +kubebuilder:object:root=true - // Status defines the current state of GatewayClass. - // - // Implementations MUST populate status on all GatewayClass resources which - // specify their controller name. - // - // +kubebuilder:default={conditions: {{type: "Accepted", status: "Unknown", message: "Waiting for controller", reason: "Waiting", lastTransitionTime: "1970-01-01T00:00:00Z"}}} - Status GatewayClassStatus `json:"status,omitempty"` +// GatewayClassList contains a list of GatewayClass +type GatewayClassList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []GatewayClass `json:"items"` } -const ( - // GatewayClassFinalizerGatewaysExist should be added as a finalizer to the - // GatewayClass whenever there are provisioned Gateways using a - // GatewayClass. - GatewayClassFinalizerGatewaysExist = "gateway-exists-finalizer.gateway.networking.k8s.io" -) - // GatewayClassSpec reflects the configuration of a class of Gateways. -type GatewayClassSpec struct { - // 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. - // - // Support: Core - // - // +kubebuilder:validation:XValidation:message="Value is immutable",rule="self == oldSelf" - 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 - // controller does not require any additional configuration. - // - // 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. - // - // If the referent cannot be found, the GatewayClass's "InvalidParameters" - // status condition will be true. - // - // Support: Implementation-specific - // - // +optional - ParametersRef *ParametersReference `json:"parametersRef,omitempty"` - - // Description helps describe a GatewayClass with more details. - // - // +kubebuilder:validation:MaxLength=64 - // +optional - Description *string `json:"description,omitempty"` -} +// +k8s:deepcopy-gen=false +type GatewayClassSpec = v1.GatewayClassSpec // ParametersReference identifies an API object containing controller-specific // configuration resource within the cluster. -type ParametersReference struct { - // Group is the group of the referent. - Group Group `json:"group"` - - // Kind is kind of the referent. - Kind Kind `json:"kind"` - - // Name is the name of the referent. - // - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:MaxLength=253 - Name string `json:"name"` - - // 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. - // - // +optional - Namespace *Namespace `json:"namespace,omitempty"` -} +// +k8s:deepcopy-gen=false +type ParametersReference = v1.ParametersReference // GatewayClassConditionType is the type for status conditions on // Gateway resources. This type should be used with the // GatewayClassStatus.Conditions field. -type GatewayClassConditionType string +// +k8s:deepcopy-gen=false +type GatewayClassConditionType = v1.GatewayClassConditionType // GatewayClassConditionReason defines the set of reasons that explain why a // particular GatewayClass condition type has been raised. -type GatewayClassConditionReason string - -const ( - // This condition indicates whether the GatewayClass has been accepted by - // the controller requested in the `spec.controller` field. - // - // 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: - // - // * "Accepted" - // - // Possible reasons for this condition to be False are: - // - // * "InvalidParameters" - // * "UnsupportedVersion" - // - // Possible reasons for this condition to be Unknown are: - // - // * "Pending" - // - // Controllers should prefer to use the values of GatewayClassConditionReason - // for the corresponding Reason, where appropriate. - GatewayClassConditionStatusAccepted GatewayClassConditionType = "Accepted" - - // This reason is used with the "Accepted" condition when the condition is - // true. - GatewayClassReasonAccepted GatewayClassConditionReason = "Accepted" - - // 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 "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. - GatewayClassReasonPending GatewayClassConditionReason = "Pending" - - // Deprecated: Use "Pending" instead. - GatewayClassReasonWaiting GatewayClassConditionReason = "Waiting" -) - -const ( - // This condition indicates whether the GatewayClass supports the version(s) - // of Gateway API CRDs present in the cluster. This condition MUST be set by - // a controller when it marks a GatewayClass "Accepted". - // - // The version of a Gateway API CRD is defined by the - // gateway.networking.k8s.io/bundle-version annotation on the CRD. If - // implementations detect any Gateway API CRDs that either do not have this - // annotation set, or have it set to a version that is not recognized or - // supported by the implementation, this condition MUST be set to false. - // - // Implementations MAY choose to either provide "best effort" support when - // an unrecognized CRD version is present. This would be communicated by - // setting the "Accepted" condition to true and the "SupportedVersion" - // condition to false. - // - // Alternatively, implementations MAY choose not to support CRDs with - // unrecognized versions. This would be communicated by setting the - // "Accepted" condition to false with the reason "UnsupportedVersions". - // - // Possible reasons for this condition to be true are: - // - // * "SupportedVersion" - // - // Possible reasons for this condition to be False are: - // - // * "UnsupportedVersion" - // - // Controllers should prefer to use the values of GatewayClassConditionReason - // for the corresponding Reason, where appropriate. - GatewayClassConditionStatusSupportedVersion GatewayClassConditionType = "SupportedVersion" - - // This reason is used with the "SupportedVersion" condition when the - // condition is true. - GatewayClassReasonSupportedVersion GatewayClassConditionReason = "SupportedVersion" - - // This reason is used with the "SupportedVersion" or "Accepted" condition - // when the condition is false. A message SHOULD be included in this - // condition that includes the detected CRD version(s) present in the - // cluster and the CRD version(s) that are supported by the GatewayClass. - GatewayClassReasonUnsupportedVersion GatewayClassConditionReason = "UnsupportedVersion" -) +// +k8s:deepcopy-gen=false +type GatewayClassConditionReason = v1.GatewayClassConditionReason // GatewayClassStatus is the current status for the GatewayClass. -type GatewayClassStatus struct { - // Conditions is the current status from the controller for - // this GatewayClass. - // - // Controllers should prefer to publish conditions using values - // of GatewayClassConditionType for the type of each Condition. - // - // +optional - // +listType=map - // +listMapKey=type - // +kubebuilder:validation:MaxItems=8 - // +kubebuilder:default={{type: "Accepted", status: "Unknown", message: "Waiting for controller", reason: "Pending", lastTransitionTime: "1970-01-01T00:00:00Z"}} - Conditions []metav1.Condition `json:"conditions,omitempty"` - - // SupportedFeatures is the set of features the GatewayClass support. - // It MUST be sorted in ascending alphabetical order. - // +optional - // +listType=set - // - // +kubebuilder:validation:MaxItems=64 - SupportedFeatures []SupportedFeature `json:"supportedFeatures,omitempty"` -} - -// +kubebuilder:object:root=true - -// GatewayClassList contains a list of GatewayClass -type GatewayClassList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []GatewayClass `json:"items"` -} - -// SupportedFeature is used to describe distinct features that are covered by -// conformance tests. -// +kubebuilder:validation:Enum=Gateway;GatewayPort8080;GatewayStaticAddresses;HTTPRoute;HTTPRouteDestinationPortMatching;HTTPRouteHostRewrite;HTTPRouteMethodMatching;HTTPRoutePathRedirect;HTTPRoutePathRewrite;HTTPRoutePortRedirect;HTTPRouteQueryParamMatching;HTTPRouteRequestMirror;HTTPRouteRequestMultipleMirrors;HTTPRouteResponseHeaderModification;HTTPRouteSchemeRedirect;Mesh;ReferenceGrant;TLSRoute -type SupportedFeature string +// +k8s:deepcopy-gen=false +type GatewayClassStatus = v1.GatewayClassStatus diff --git a/apis/v1beta1/httproute_types.go b/apis/v1beta1/httproute_types.go index b9566cdbba..1d869e09b9 100644 --- a/apis/v1beta1/httproute_types.go +++ b/apis/v1beta1/httproute_types.go @@ -18,6 +18,8 @@ package v1beta1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + v1 "sigs.k8s.io/gateway-api/apis/v1" ) // +genclient @@ -32,16 +34,7 @@ import ( // 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"` - - // Spec defines the desired state of HTTPRoute. - Spec HTTPRouteSpec `json:"spec"` - - // Status defines the current state of HTTPRoute. - Status HTTPRouteStatus `json:"status,omitempty"` -} +type HTTPRoute v1.HTTPRoute // +kubebuilder:object:root=true @@ -53,271 +46,17 @@ type HTTPRouteList struct { } // HTTPRouteSpec defines the desired state of HTTPRoute -type HTTPRouteSpec struct { - CommonRouteSpec `json:",inline"` - - // Hostnames defines a set of hostnames that should match against the HTTP Host - // header to select a HTTPRoute used to process the request. Implementations - // MUST ignore any port value specified in the HTTP Host header while - // performing a match and (absent of any applicable header modification - // configuration) MUST forward this header unmodified to the backend. - // - // Valid values for Hostnames are determined by RFC 1123 definition of a - // hostname with 2 notable exceptions: - // - // 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. - // - // 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: - // - // * 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, - // `*.example.com`, `test.example.com`, and `foo.test.example.com` would - // all match. On the other hand, `example.com` and `test.example.net` would - // not match. - // - // Hostnames that are prefixed with a wildcard label (`*.`) are interpreted - // as a suffix match. That means that a match for `*.example.com` would match - // both `test.example.com`, and `foo.test.example.com`, but not `example.com`. - // - // 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. - // - // 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. - // - // In the event that multiple HTTPRoutes specify intersecting hostnames (e.g. - // overlapping wildcard matching and exact matching hostnames), precedence must - // be given to rules from the HTTPRoute with the largest number of: - // - // * Characters in a matching non-wildcard hostname. - // * Characters in a matching hostname. - // - // If ties exist across multiple Routes, the matching precedence rules for - // HTTPRouteMatches takes over. - // - // Support: Core - // - // +optional - // +kubebuilder:validation:MaxItems=16 - Hostnames []Hostname `json:"hostnames,omitempty"` - - // Rules are a list of HTTP matchers, filters and actions. - // - // +optional - // +kubebuilder:validation:MaxItems=16 - // +kubebuilder:default={{matches: {{path: {type: "PathPrefix", value: "/"}}}}} - Rules []HTTPRouteRule `json:"rules,omitempty"` -} +// +k8s:deepcopy-gen=false +type HTTPRouteSpec = v1.HTTPRouteSpec // HTTPRouteRule defines semantics for matching an HTTP request based on // conditions (matches), processing it (filters), and forwarding the request to // an API object (backendRefs). -// -// +kubebuilder:validation:XValidation:message="RequestRedirect filter must not be used together with backendRefs",rule="(has(self.backendRefs) && size(self.backendRefs) > 0) ? (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): true" -// +kubebuilder:validation:XValidation:message="When using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified",rule="(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == 'ReplacePrefixMatch' && has(f.requestRedirect.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" -// +kubebuilder:validation:XValidation:message="When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified",rule="(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == 'ReplacePrefixMatch' && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" -// +kubebuilder:validation:XValidation:message="Within backendRefs, when using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified",rule="(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == 'ReplacePrefixMatch' && has(f.requestRedirect.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" -// +kubebuilder:validation:XValidation:message="Within backendRefs, When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified",rule="(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == 'ReplacePrefixMatch' && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" -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 - // if **any** one of the matches is satisfied. - // - // For example, take the following matches configuration: - // - // ``` - // matches: - // - path: - // value: "/foo" - // headers: - // - name: "version" - // value: "v2" - // - path: - // value: "/v2/foo" - // ``` - // - // For a request to match against this rule, a request must satisfy - // EITHER of the two conditions: - // - // - path prefixed with `/foo` AND contains the header `version: v2` - // - path prefix of `/v2/foo` - // - // See the documentation for HTTPRouteMatch on how to specify multiple - // match conditions that should be ANDed together. - // - // If no matches are specified, the default is a prefix - // path match on "/", which has the effect of matching every - // HTTP request. - // - // Proxy or Load Balancer routing configuration generated from HTTPRoutes - // MUST prioritize matches based on the following criteria, continuing on - // ties. Across all rules specified on applicable Routes, precedence must be - // given to the match having: - // - // * "Exact" path match. - // * "Prefix" path match with largest number of characters. - // * Method match. - // * Largest number of header matches. - // * Largest number of query param matches. - // - // Note: The precedence of RegularExpression path matches are implementation-specific. - // - // 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. - // * The Route appearing first in alphabetical order by - // "{namespace}/{name}". - // - // If ties still exist within an HTTPRoute, matching precedence MUST be granted - // to the FIRST matching rule (in list order) with a match meeting the above - // criteria. - // - // When no rules matching a request have been successfully attached to the - // parent a request is coming from, a HTTP 404 status code MUST be returned. - // - // +optional - // +kubebuilder:validation:MaxItems=8 - // +kubebuilder:default={{path:{ type: "PathPrefix", value: "/"}}} - Matches []HTTPRouteMatch `json:"matches,omitempty"` - - // Filters define the filters that are applied to requests that match - // this rule. - // - // The effects of ordering of multiple behaviors are currently unspecified. - // This can change in the future based on feedback during the alpha stage. - // - // Conformance-levels at this level are defined based on the type of filter: - // - // - 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. - // - // Specifying the same filter multiple times is not supported unless explicitly - // indicated in the filter. - // - // All filters are expected to be compatible with each other except for the - // URLRewrite and RequestRedirect filters, which may not be combined. If an - // implementation can not support other combinations of filters, they must clearly - // document that limitation. In cases where incompatible or unsupported - // filters are specified and cause the `Accepted` condition to be set to status - // `False`, implementations may use the `IncompatibleFilters` reason to specify - // this configuration error. - // - // Support: Core - // - // +optional - // +kubebuilder:validation:MaxItems=16 - // +kubebuilder:validation:XValidation:message="May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both",rule="!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" - // +kubebuilder:validation:XValidation:message="RequestHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1" - // +kubebuilder:validation:XValidation:message="ResponseHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1" - // +kubebuilder:validation:XValidation:message="RequestRedirect filter cannot be repeated",rule="self.filter(f, f.type == 'RequestRedirect').size() <= 1" - // +kubebuilder:validation:XValidation:message="URLRewrite filter cannot be repeated",rule="self.filter(f, f.type == 'URLRewrite').size() <= 1" - Filters []HTTPRouteFilter `json:"filters,omitempty"` - - // BackendRefs defines the backend(s) where matching requests should be - // sent. - // - // Failure behavior here depends on how many BackendRefs are specified and - // how many are invalid. - // - // If *all* entries in BackendRefs are invalid, and there are also no filters - // specified in this route rule, *all* traffic which matches this rule MUST - // receive a 500 status code. - // - // See the HTTPBackendRef definition for the rules about what makes a single - // HTTPBackendRef invalid. - // - // When a HTTPBackendRef is invalid, 500 status codes MUST be returned for - // requests that would have otherwise been routed to an invalid backend. If - // multiple backends are specified, and some are invalid, the proportion of - // requests that would otherwise have been routed to an invalid backend - // MUST receive a 500 status code. - // - // For example, if two backends are specified with equal weights, and one is - // invalid, 50 percent of traffic must receive a 500. Implementations may - // choose how that 50 percent is determined. - // - // Support: Core for Kubernetes Service - // - // Support: Extended for Kubernetes ServiceImport - // - // Support: Implementation-specific for any other resource - // - // Support for weight: Core - // - // +optional - // +kubebuilder:validation:MaxItems=16 - BackendRefs []HTTPBackendRef `json:"backendRefs,omitempty"` - - // Timeouts defines the timeouts that can be configured for an HTTP request. - // - // Support: Extended - // - // +optional - // - Timeouts *HTTPRouteTimeouts `json:"timeouts,omitempty"` -} - -// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute. -// Timeout values are represented with Gateway API Duration formatting. -// Specifying a zero value such as "0s" is interpreted as no timeout. -// -// +kubebuilder:validation:XValidation:message="backendRequest timeout cannot be longer than request timeout",rule="!(has(self.request) && has(self.backendRequest) && duration(self.request) != duration('0s') && duration(self.backendRequest) > duration(self.request))" -type HTTPRouteTimeouts struct { - // Request specifies the maximum duration for a gateway to respond to an HTTP request. - // If the gateway has not been able to respond before this deadline is met, the gateway - // MUST return a timeout error. - // - // For example, setting the `rules.timeouts.request` field to the value `10s` in an - // `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds - // to complete. - // - // This timeout is intended to cover as close to the whole request-response transaction - // as possible although an implementation MAY choose to start the timeout after the entire - // request stream has been received instead of immediately after the transaction is - // initiated by the client. - // - // When this field is unspecified, request timeout behavior is implementation-specific. - // - // Support: Extended - // - // +optional - Request *Duration `json:"request,omitempty"` - - // BackendRequest specifies a timeout for an individual request from the gateway - // to a backend. This covers the time from when the request first starts being - // sent from the gateway to when the full response has been received from the backend. - // - // An entire client HTTP transaction with a gateway, covered by the Request timeout, - // may result in more than one call from the gateway to the destination backend, - // for example, if automatic retries are supported. - // - // Because the Request timeout encompasses the BackendRequest timeout, the value of - // BackendRequest must be <= the value of Request timeout. - // - // Support: Extended - // - // +optional - BackendRequest *Duration `json:"backendRequest,omitempty"` -} +// +k8s:deepcopy-gen=false +type HTTPRouteRule = v1.HTTPRouteRule // PathMatchType specifies the semantics of how HTTP paths should be compared. -// Valid PathMatchType values, along with their support levels, are: +// Valid PathMatchType values, along with their conformance level, are: // // * "Exact" - Core // * "PathPrefix" - Core @@ -336,68 +75,12 @@ type HTTPRouteTimeouts struct { // Reason of `UnsupportedValue`. // // +kubebuilder:validation:Enum=Exact;PathPrefix;RegularExpression -type PathMatchType string - -const ( - // Matches the URL path exactly and with case sensitivity. This means that - // an exact path match on `/abc` will only match requests to `/abc`, NOT - // `/abc/`, `/Abc`, or `/abcd`. - PathMatchExact PathMatchType = "Exact" - - // Matches based on a URL path prefix split by `/`. Matching is - // case sensitive and done on a path element by element basis. A - // path element refers to the list of labels in the path split by - // the `/` separator. When specified, a trailing `/` is ignored. - // - // For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match - // the prefix `/abc`, but the path `/abcd` would not. - // - // "PathPrefix" is semantically equivalent to the "Prefix" path type in the - // Kubernetes Ingress API. - PathMatchPathPrefix PathMatchType = "PathPrefix" - - // Matches if the URL path matches the given regular expression with - // case sensitivity. - // - // Since `"RegularExpression"` has implementation-specific conformance, - // implementations can support POSIX, PCRE, RE2 or any other regular expression - // dialect. - // Please read the implementation's documentation to determine the supported - // dialect. - PathMatchRegularExpression PathMatchType = "RegularExpression" -) +// +k8s:deepcopy-gen=false +type PathMatchType = v1.PathMatchType // HTTPPathMatch describes how to select a HTTP route by matching the HTTP request path. -// -// +kubebuilder:validation:XValidation:message="value must be an absolute path and start with '/' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? self.value.startsWith('/') : true" -// +kubebuilder:validation:XValidation:message="must not contain '//' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.contains('//') : true" -// +kubebuilder:validation:XValidation:message="must not contain '/./' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.contains('/./') : true" -// +kubebuilder:validation:XValidation:message="must not contain '/../' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.contains('/../') : true" -// +kubebuilder:validation:XValidation:message="must not contain '%2f' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.contains('%2f') : true" -// +kubebuilder:validation:XValidation:message="must not contain '%2F' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.contains('%2F') : true" -// +kubebuilder:validation:XValidation:message="must not contain '#' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.contains('#') : true" -// +kubebuilder:validation:XValidation:message="must not end with '/..' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.endsWith('/..') : true" -// +kubebuilder:validation:XValidation:message="must not end with '/.' when type one of ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? !self.value.endsWith('/.') : true" -// +kubebuilder:validation:XValidation:message="type must be one of ['Exact', 'PathPrefix', 'RegularExpression']",rule="self.type in ['Exact','PathPrefix'] || self.type == 'RegularExpression'" -// +kubebuilder:validation:XValidation:message="must only contain valid characters (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) for types ['Exact', 'PathPrefix']",rule="(self.type in ['Exact','PathPrefix']) ? self.value.matches(r\"\"\"^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$\"\"\") : true" -type HTTPPathMatch struct { - // Type specifies how to match against the path Value. - // - // Support: Core (Exact, PathPrefix) - // - // Support: Implementation-specific (RegularExpression) - // - // +optional - // +kubebuilder:default=PathPrefix - Type *PathMatchType `json:"type,omitempty"` - - // Value of the HTTP path to match against. - // - // +optional - // +kubebuilder:default="/" - // +kubebuilder:validation:MaxLength=1024 - Value *string `json:"value,omitempty"` -} +// +k8s:deepcopy-gen=false +type HTTPPathMatch = v1.HTTPPathMatch // HeaderMatchType specifies the semantics of how HTTP header values should be // compared. Valid HeaderMatchType values, along with their conformance levels, are: @@ -413,18 +96,12 @@ type HTTPPathMatch struct { // Reason of `UnsupportedValue`. // // +kubebuilder:validation:Enum=Exact;RegularExpression -type HeaderMatchType string - -// HeaderMatchType constants. -const ( - HeaderMatchExact HeaderMatchType = "Exact" - HeaderMatchRegularExpression HeaderMatchType = "RegularExpression" -) +// +k8s:deepcopy-gen=false +type HeaderMatchType = v1.HeaderMatchType // HTTPHeaderName is the name of an HTTP header. // // Valid values include: -// // * "Authorization" // * "Set-Cookie" // @@ -432,49 +109,15 @@ const ( // // - ":method" - ":" is an invalid character. This means that HTTP/2 pseudo // headers are not currently supported by this type. -// - "/invalid" - "/ " is an invalid character -type HTTPHeaderName HeaderName +// +// * "/invalid" - "/" is an invalid character +// +k8s:deepcopy-gen=false +type HTTPHeaderName = v1.HeaderName // HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request // headers. -type HTTPHeaderMatch struct { - // Type specifies how to match against the value of the header. - // - // Support: Core (Exact) - // - // Support: Implementation-specific (RegularExpression) - // - // Since RegularExpression HeaderMatchType has implementation-specific - // conformance, implementations can support POSIX, PCRE or any other dialects - // of regular expressions. Please read the implementation's documentation to - // determine the supported dialect. - // - // +optional - // +kubebuilder:default=Exact - Type *HeaderMatchType `json:"type,omitempty"` - - // Name is the name of the HTTP Header to be matched. Name matching MUST be - // case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - // - // If multiple entries specify equivalent header names, 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. - // - // 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". - Name HTTPHeaderName `json:"name"` - - // Value is the value of HTTP Header to be matched. - // - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:MaxLength=4096 - Value string `json:"value"` -} +// +k8s:deepcopy-gen=false +type HTTPHeaderMatch = v1.HTTPHeaderMatch // QueryParamMatchType specifies the semantics of how HTTP query parameter // values should be compared. Valid QueryParamMatchType values, along with their @@ -491,57 +134,13 @@ type HTTPHeaderMatch struct { // Reason of `UnsupportedValue`. // // +kubebuilder:validation:Enum=Exact;RegularExpression -type QueryParamMatchType string - -// QueryParamMatchType constants. -const ( - QueryParamMatchExact QueryParamMatchType = "Exact" - QueryParamMatchRegularExpression QueryParamMatchType = "RegularExpression" -) +// +k8s:deepcopy-gen=false +type QueryParamMatchType = v1.QueryParamMatchType // HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP // query parameters. -type HTTPQueryParamMatch struct { - // Type specifies how to match against the value of the query parameter. - // - // Support: Extended (Exact) - // - // Support: Implementation-specific (RegularExpression) - // - // Since RegularExpression QueryParamMatchType has Implementation-specific - // conformance, implementations can support POSIX, PCRE or any other - // dialects of regular expressions. Please read the implementation's - // documentation to determine the supported dialect. - // - // +optional - // +kubebuilder:default=Exact - Type *QueryParamMatchType `json:"type,omitempty"` - - // 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). - // - // If multiple entries specify equivalent query param names, only the first - // entry with an equivalent name MUST be considered for a match. Subsequent - // entries with an equivalent query param name MUST be ignored. - // - // If a query param is repeated in an HTTP request, the behavior is - // purposely left undefined, since different data planes have different - // capabilities. However, it is *recommended* that implementations should - // match against the first value of the param if the data plane supports it, - // as this behavior is expected in other load balancing contexts outside of - // the Gateway API. - // - // Users SHOULD NOT route traffic based on repeated query params to guard - // themselves against potential differences in the implementations. - Name HTTPHeaderName `json:"name"` - - // Value is the value of HTTP query param to be matched. - // - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:MaxLength=1024 - Value string `json:"value"` -} +// +k8s:deepcopy-gen=false +type HTTPQueryParamMatch = v1.HTTPQueryParamMatch // HTTPMethod describes how to select a HTTP route by matching the HTTP // method as defined by @@ -557,19 +156,8 @@ type HTTPQueryParamMatch struct { // Reason of `UnsupportedValue`. // // +kubebuilder:validation:Enum=GET;HEAD;POST;PUT;DELETE;CONNECT;OPTIONS;TRACE;PATCH -type HTTPMethod string - -const ( - HTTPMethodGet HTTPMethod = "GET" - HTTPMethodHead HTTPMethod = "HEAD" - HTTPMethodPost HTTPMethod = "POST" - HTTPMethodPut HTTPMethod = "PUT" - HTTPMethodDelete HTTPMethod = "DELETE" - HTTPMethodConnect HTTPMethod = "CONNECT" - HTTPMethodOptions HTTPMethod = "OPTIONS" - HTTPMethodTrace HTTPMethod = "TRACE" - HTTPMethodPatch HTTPMethod = "PATCH" -) +// +k8s:deepcopy-gen=false +type HTTPMethod = v1.HTTPMethod // HTTPRouteMatch defines the predicate used to match requests to a given // action. Multiple match types are ANDed together, i.e. the match will @@ -588,45 +176,8 @@ const ( // value "v1" // // ``` -type HTTPRouteMatch struct { - // Path specifies a HTTP request path matcher. If this field is not - // specified, a default prefix match on the "/" path is provided. - // - // +optional - // +kubebuilder:default={type: "PathPrefix", value: "/"} - Path *HTTPPathMatch `json:"path,omitempty"` - - // 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. - // - // +listType=map - // +listMapKey=name - // +optional - // +kubebuilder:validation:MaxItems=16 - Headers []HTTPHeaderMatch `json:"headers,omitempty"` - - // 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. - // - // Support: Extended - // - // +listType=map - // +listMapKey=name - // +optional - // +kubebuilder:validation:MaxItems=16 - QueryParams []HTTPQueryParamMatch `json:"queryParams,omitempty"` - - // Method specifies HTTP method matcher. - // When specified, this route will be matched only if the request has the - // specified method. - // - // Support: Extended - // - // +optional - Method *HTTPMethod `json:"method,omitempty"` -} +// +k8s:deepcopy-gen=false +type HTTPRouteMatch = v1.HTTPRouteMatch // HTTPRouteFilter defines processing steps that must be completed during the // request or response lifecycle. HTTPRouteFilters are meant as an extension @@ -634,569 +185,58 @@ type HTTPRouteMatch struct { // 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. -// -// +kubebuilder:validation:XValidation:message="filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier",rule="!(has(self.requestHeaderModifier) && self.type != 'RequestHeaderModifier')" -// +kubebuilder:validation:XValidation:message="filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type",rule="!(!has(self.requestHeaderModifier) && self.type == 'RequestHeaderModifier')" -// +kubebuilder:validation:XValidation:message="filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier",rule="!(has(self.responseHeaderModifier) && self.type != 'ResponseHeaderModifier')" -// +kubebuilder:validation:XValidation:message="filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type",rule="!(!has(self.responseHeaderModifier) && self.type == 'ResponseHeaderModifier')" -// +kubebuilder:validation:XValidation:message="filter.requestMirror must be nil if the filter.type is not RequestMirror",rule="!(has(self.requestMirror) && self.type != 'RequestMirror')" -// +kubebuilder:validation:XValidation:message="filter.requestMirror must be specified for RequestMirror filter.type",rule="!(!has(self.requestMirror) && self.type == 'RequestMirror')" -// +kubebuilder:validation:XValidation:message="filter.requestRedirect must be nil if the filter.type is not RequestRedirect",rule="!(has(self.requestRedirect) && self.type != 'RequestRedirect')" -// +kubebuilder:validation:XValidation:message="filter.requestRedirect must be specified for RequestRedirect filter.type",rule="!(!has(self.requestRedirect) && self.type == 'RequestRedirect')" -// +kubebuilder:validation:XValidation:message="filter.urlRewrite must be nil if the filter.type is not URLRewrite",rule="!(has(self.urlRewrite) && self.type != 'URLRewrite')" -// +kubebuilder:validation:XValidation:message="filter.urlRewrite must be specified for URLRewrite filter.type",rule="!(!has(self.urlRewrite) && self.type == 'URLRewrite')" -// +kubebuilder:validation:XValidation:message="filter.extensionRef must be nil if the filter.type is not ExtensionRef",rule="!(has(self.extensionRef) && self.type != 'ExtensionRef')" -// +kubebuilder:validation:XValidation:message="filter.extensionRef must be specified for ExtensionRef filter.type",rule="!(!has(self.extensionRef) && self.type == 'ExtensionRef')" -type HTTPRouteFilter struct { - // Type identifies the type of filter to apply. As with other API fields, - // types are classified into three conformance levels: - // - // - Core: Filter types and their corresponding configuration defined by - // "Support: Core" in this package, e.g. "RequestHeaderModifier". All - // implementations must support core filters. - // - // - Extended: Filter types and their corresponding configuration defined by - // "Support: Extended" in this package, e.g. "RequestMirror". Implementers - // are encouraged to support extended filters. - // - // - Implementation-specific: Filters that are defined and supported by - // specific vendors. - // In the future, filters showing convergence in behavior across multiple - // implementations will be considered for inclusion in extended or core - // conformance levels. Filter-specific configuration for such filters - // is specified using the ExtensionRef field. `Type` should be set to - // "ExtensionRef" for custom filters. - // - // Implementers are encouraged to define custom implementation types to - // extend the core API with implementation-specific behavior. - // - // If a reference to a custom filter type cannot be resolved, the filter - // MUST NOT be skipped. Instead, requests that would have been processed by - // that filter MUST receive a HTTP error response. - // - // Note that values may be added to this enum, implementations - // must ensure that unknown values will not cause a crash. - // - // Unknown values here must result in the implementation setting the - // Accepted Condition for the Route to `status: False`, with a - // Reason of `UnsupportedValue`. - // - // +unionDiscriminator - // +kubebuilder:validation:Enum=RequestHeaderModifier;ResponseHeaderModifier;RequestMirror;RequestRedirect;URLRewrite;ExtensionRef - Type HTTPRouteFilterType `json:"type"` - - // RequestHeaderModifier defines a schema for a filter that modifies request - // headers. - // - // Support: Core - // - // +optional - RequestHeaderModifier *HTTPHeaderFilter `json:"requestHeaderModifier,omitempty"` - - // ResponseHeaderModifier defines a schema for a filter that modifies response - // headers. - // - // Support: Extended - // - // +optional - ResponseHeaderModifier *HTTPHeaderFilter `json:"responseHeaderModifier,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. - // - // This filter can be used multiple times within the same rule. Note that - // not all implementations will be able to support mirroring to multiple - // backends. - // - // Support: Extended - // - // +optional - RequestMirror *HTTPRequestMirrorFilter `json:"requestMirror,omitempty"` - - // RequestRedirect defines a schema for a filter that responds to the - // request with an HTTP redirection. - // - // Support: Core - // - // +optional - RequestRedirect *HTTPRequestRedirectFilter `json:"requestRedirect,omitempty"` - - // URLRewrite defines a schema for a filter that modifies a request during forwarding. - // - // Support: Extended - // - // +optional - URLRewrite *HTTPURLRewriteFilter `json:"urlRewrite,omitempty"` - - // ExtensionRef is an optional, implementation-specific extension to the - // "filter" behavior. For example, resource "myroutefilter" in group - // "networking.example.net"). ExtensionRef MUST NOT be used for core and - // extended filters. - // - // This filter can be used multiple times within the same rule. - // - // Support: Implementation-specific - // - // +optional - ExtensionRef *LocalObjectReference `json:"extensionRef,omitempty"` -} +// +k8s:deepcopy-gen=false +type HTTPRouteFilter = v1.HTTPRouteFilter // HTTPRouteFilterType identifies a type of HTTPRoute filter. -type HTTPRouteFilterType string - -const ( - // HTTPRouteFilterRequestHeaderModifier can be used to add or remove an HTTP - // header from an HTTP request before it is sent to the upstream target. - // - // Support in HTTPRouteRule: Core - // - // Support in HTTPBackendRef: Extended - HTTPRouteFilterRequestHeaderModifier HTTPRouteFilterType = "RequestHeaderModifier" - - // HTTPRouteFilterResponseHeaderModifier can be used to add or remove an HTTP - // header from an HTTP response before it is sent to the client. - // - // Support in HTTPRouteRule: Extended - // - // Support in HTTPBackendRef: Extended - HTTPRouteFilterResponseHeaderModifier HTTPRouteFilterType = "ResponseHeaderModifier" - - // HTTPRouteFilterRequestRedirect can be used to redirect a request to - // another location. This filter can also be used for HTTP to HTTPS - // redirects. This may not be used on the same Route rule or BackendRef as a - // URLRewrite filter. - // - // Support in HTTPRouteRule: Core - // - // Support in HTTPBackendRef: Extended - HTTPRouteFilterRequestRedirect HTTPRouteFilterType = "RequestRedirect" - - // HTTPRouteFilterURLRewrite can be used to modify a request during - // forwarding. At most one of these filters may be used on a Route rule. - // This may not be used on the same Route rule or BackendRef as a - // RequestRedirect filter. - // - // Support in HTTPRouteRule: Extended - // - // Support in HTTPBackendRef: Extended - HTTPRouteFilterURLRewrite HTTPRouteFilterType = "URLRewrite" - - // HTTPRouteFilterRequestMirror can be used to mirror HTTP requests to a - // different backend. The responses from this backend MUST be ignored by - // the Gateway. - // - // Support in HTTPRouteRule: Extended - // - // Support in HTTPBackendRef: Extended - HTTPRouteFilterRequestMirror HTTPRouteFilterType = "RequestMirror" +// +k8s:deepcopy-gen=false +type HTTPRouteFilterType = v1.HTTPRouteFilterType - // HTTPRouteFilterExtensionRef should be used for configuring custom - // HTTP filters. - // - // Support in HTTPRouteRule: Implementation-specific - // - // Support in HTTPBackendRef: Implementation-specific - HTTPRouteFilterExtensionRef HTTPRouteFilterType = "ExtensionRef" -) +// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute. +// +k8s:deepcopy-gen=false +type HTTPRouteTimeouts = v1.HTTPRouteTimeouts // HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. -type HTTPHeader struct { - // Name is the name of the HTTP Header to be matched. Name matching MUST be - // case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - // - // If multiple entries specify equivalent header names, the first entry with - // an equivalent name MUST be considered for a match. Subsequent entries - // with an equivalent header name MUST be ignored. Due to the - // case-insensitivity of header names, "foo" and "Foo" are considered - // equivalent. - Name HTTPHeaderName `json:"name"` - - // Value is the value of HTTP Header to be matched. - // - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:MaxLength=4096 - Value string `json:"value"` -} - -// HTTPHeaderFilter defines a filter that modifies the headers of an HTTP -// request or response. Only one action for a given header name is permitted. -// Filters specifying multiple actions of the same or different type for any one -// header name are invalid and will be rejected by the webhook if installed. -// Configuration to set or add multiple values for a header must use RFC 7230 -// header value formatting, separating each value with a comma. -type HTTPHeaderFilter struct { - // Set overwrites the request with the given header (name, value) - // before the action. - // - // Input: - // GET /foo HTTP/1.1 - // my-header: foo - // - // Config: - // set: - // - name: "my-header" - // value: "bar" - // - // Output: - // GET /foo HTTP/1.1 - // my-header: bar - // - // +optional - // +listType=map - // +listMapKey=name - // +kubebuilder:validation:MaxItems=16 - Set []HTTPHeader `json:"set,omitempty"` +// +k8s:deepcopy-gen=false +type HTTPHeader = v1.HTTPHeader - // Add adds the given header(s) (name, value) to the request - // before the action. It appends to any existing values associated - // with the header name. - // - // Input: - // GET /foo HTTP/1.1 - // my-header: foo - // - // Config: - // add: - // - name: "my-header" - // value: "bar,baz" - // - // Output: - // GET /foo HTTP/1.1 - // my-header: foo,bar,baz - // - // +optional - // +listType=map - // +listMapKey=name - // +kubebuilder:validation:MaxItems=16 - Add []HTTPHeader `json:"add,omitempty"` - - // Remove the given header(s) from the HTTP request before the action. The - // value of Remove is a list of HTTP header names. Note that the header - // names are case-insensitive (see - // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - // - // Input: - // GET /foo HTTP/1.1 - // my-header1: foo - // my-header2: bar - // my-header3: baz - // - // Config: - // remove: ["my-header1", "my-header3"] - // - // Output: - // GET /foo HTTP/1.1 - // my-header2: bar - // - // +optional - // +listType=set - // +kubebuilder:validation:MaxItems=16 - Remove []string `json:"remove,omitempty"` -} +// HTTPHeaderFilter defines a filter that modifies the headers of an HTTP request +// or response. +// +k8s:deepcopy-gen=false +type HTTPHeaderFilter = v1.HTTPHeaderFilter // HTTPPathModifierType defines the type of path redirect or rewrite. -type HTTPPathModifierType string - -const ( - // This type of modifier indicates that the full path will be replaced - // by the specified value. - FullPathHTTPPathModifier HTTPPathModifierType = "ReplaceFullPath" - - // This type of modifier indicates that any prefix path matches will be - // replaced by the substitution value. For example, a path with a prefix - // match of "/foo" and a ReplacePrefixMatch substitution of "/bar" will have - // the "/foo" prefix replaced with "/bar" in matching requests. - // - // Note that this matches the behavior of the PathPrefix match type. This - // matches full path elements. A path element refers to the list of labels - // in the path split by the `/` separator. When specified, a trailing `/` is - // ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - // match the prefix `/abc`, but the path `/abcd` would not. - PrefixMatchHTTPPathModifier HTTPPathModifierType = "ReplacePrefixMatch" -) +// +k8s:deepcopy-gen=false +type HTTPPathModifierType = v1.HTTPPathModifierType // HTTPPathModifier defines configuration for path modifiers. -// -// +kubebuilder:validation:XValidation:message="replaceFullPath must be specified when type is set to 'ReplaceFullPath'",rule="self.type == 'ReplaceFullPath' ? has(self.replaceFullPath) : true" -// +kubebuilder:validation:XValidation:message="type must be 'ReplaceFullPath' when replaceFullPath is set",rule="has(self.replaceFullPath) ? self.type == 'ReplaceFullPath' : true" -// +kubebuilder:validation:XValidation:message="replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch'",rule="self.type == 'ReplacePrefixMatch' ? has(self.replacePrefixMatch) : true" -// +kubebuilder:validation:XValidation:message="type must be 'ReplacePrefixMatch' when replacePrefixMatch is set",rule="has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" -type HTTPPathModifier struct { - // Type defines the type of path modifier. Additional types may be - // added in a future release of the API. - // - // Note that values may be added to this enum, implementations - // must ensure that unknown values will not cause a crash. - // - // Unknown values here must result in the implementation setting the - // Accepted Condition for the Route to `status: False`, with a - // Reason of `UnsupportedValue`. - // - // +kubebuilder:validation:Enum=ReplaceFullPath;ReplacePrefixMatch - Type HTTPPathModifierType `json:"type"` - - // ReplaceFullPath specifies the value with which to replace the full path - // of a request during a rewrite or redirect. - // - // +kubebuilder:validation:MaxLength=1024 - // +optional - ReplaceFullPath *string `json:"replaceFullPath,omitempty"` - - // ReplacePrefixMatch specifies the value with which to replace the prefix - // match of a request during a rewrite or redirect. For example, a request - // to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - // of "/xyz" would be modified to "/xyz/bar". - // - // Note that this matches the behavior of the PathPrefix match type. This - // matches full path elements. A path element refers to the list of labels - // in the path split by the `/` separator. When specified, a trailing `/` is - // ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - // match the prefix `/abc`, but the path `/abcd` would not. - // - // ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - // Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - // the implementation setting the Accepted Condition for the Route to `status: False`. - // - // Request Path | Prefix Match | Replace Prefix | Modified Path - // -------------|--------------|----------------|---------- - // /foo/bar | /foo | /xyz | /xyz/bar - // /foo/bar | /foo | /xyz/ | /xyz/bar - // /foo/bar | /foo/ | /xyz | /xyz/bar - // /foo/bar | /foo/ | /xyz/ | /xyz/bar - // /foo | /foo | /xyz | /xyz - // /foo/ | /foo | /xyz | /xyz/ - // /foo/bar | /foo | | /bar - // /foo/ | /foo | | / - // /foo | /foo | | / - // /foo/ | /foo | / | / - // /foo | /foo | / | / - // - // +kubebuilder:validation:MaxLength=1024 - // +optional - ReplacePrefixMatch *string `json:"replacePrefixMatch,omitempty"` -} +// +// +k8s:deepcopy-gen=false +type HTTPPathModifier = v1.HTTPPathModifier // HTTPRequestRedirect defines a filter that redirects a request. This filter // MUST NOT be used on the same Route rule as a HTTPURLRewrite filter. -type HTTPRequestRedirectFilter struct { - // Scheme is the scheme to be used in the value of the `Location` header in - // the response. When empty, the scheme of the request is used. - // - // Scheme redirects can affect the port of the redirect, for more information, - // refer to the documentation for the port field of this filter. - // - // Note that values may be added to this enum, implementations - // must ensure that unknown values will not cause a crash. - // - // Unknown values here must result in the implementation setting the - // Accepted Condition for the Route to `status: False`, with a - // Reason of `UnsupportedValue`. - // - // Support: Extended - // - // +optional - // +kubebuilder:validation:Enum=http;https - Scheme *string `json:"scheme,omitempty"` - - // Hostname is the hostname to be used in the value of the `Location` - // header in the response. - // When empty, the hostname in the `Host` header of the request is used. - // - // Support: Core - // - // +optional - Hostname *PreciseHostname `json:"hostname,omitempty"` - - // Path defines parameters used to modify the path of the incoming request. - // The modified path is then used to construct the `Location` header. When - // empty, the request path is used as-is. - // - // Support: Extended - // - // +optional - Path *HTTPPathModifier `json:"path,omitempty"` - - // Port is the port to be used in the value of the `Location` - // header in the response. - // - // If no port is specified, the redirect port MUST be derived using the - // following rules: - // - // * If redirect scheme is not-empty, the redirect port MUST be the well-known - // port associated with the redirect scheme. Specifically "http" to port 80 - // and "https" to port 443. If the redirect scheme does not have a - // well-known port, the listener port of the Gateway SHOULD be used. - // * If redirect scheme is empty, the redirect port MUST be the Gateway - // Listener port. - // - // Implementations SHOULD NOT add the port number in the 'Location' - // header in the following cases: - // - // * A Location header that will use HTTP (whether that is determined via - // the Listener protocol or the Scheme field) _and_ use port 80. - // * A Location header that will use HTTPS (whether that is determined via - // the Listener protocol or the Scheme field) _and_ use port 443. - // - // Support: Extended - // - // +optional - Port *PortNumber `json:"port,omitempty"` - - // StatusCode is the HTTP status code to be used in response. - // - // Note that values may be added to this enum, implementations - // must ensure that unknown values will not cause a crash. - // - // Unknown values here must result in the implementation setting the - // Accepted Condition for the Route to `status: False`, with a - // Reason of `UnsupportedValue`. - // - // Support: Core - // - // +optional - // +kubebuilder:default=302 - // +kubebuilder:validation:Enum=301;302 - StatusCode *int `json:"statusCode,omitempty"` -} +// +k8s:deepcopy-gen=false +type HTTPRequestRedirectFilter = v1.HTTPRequestRedirectFilter // HTTPURLRewriteFilter defines a filter that modifies a request during // forwarding. At most one of these filters may be used on a Route rule. This // MUST NOT be used on the same Route rule as a HTTPRequestRedirect filter. // // Support: Extended -type HTTPURLRewriteFilter struct { - // Hostname is the value to be used to replace the Host header value during - // forwarding. - // - // Support: Extended - // - // +optional - Hostname *PreciseHostname `json:"hostname,omitempty"` - - // Path defines a path rewrite. - // - // Support: Extended - // - // +optional - Path *HTTPPathModifier `json:"path,omitempty"` -} +// +// +// +k8s:deepcopy-gen=false +type HTTPURLRewriteFilter = v1.HTTPURLRewriteFilter // HTTPRequestMirrorFilter defines configuration for the RequestMirror filter. -type HTTPRequestMirrorFilter struct { - // BackendRef references a resource where mirrored requests are sent. - // - // Mirrored requests must be sent only to a single destination endpoint - // within this BackendRef, irrespective of how many endpoints are present - // within this BackendRef. - // - // If the referent cannot be found, this BackendRef is invalid and must be - // dropped from the Gateway. The controller must ensure the "ResolvedRefs" - // condition on the Route status is set to `status: False` and not configure - // this backend in the underlying implementation. - // - // If there is a cross-namespace reference to an *existing* object - // that is not allowed by a ReferenceGrant, the controller must ensure the - // "ResolvedRefs" condition on the Route is set to `status: False`, - // with the "RefNotPermitted" reason and not configure this backend in the - // underlying implementation. - // - // In either error case, the Message of the `ResolvedRefs` Condition - // should be used to provide more detail about the problem. - // - // Support: Extended for Kubernetes Service - // - // Support: Implementation-specific for any other resource - BackendRef BackendObjectReference `json:"backendRef"` -} +// +k8s:deepcopy-gen=false +type HTTPRequestMirrorFilter = v1.HTTPRequestMirrorFilter -// HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. -// -// Note that when a namespace different than the local namespace is specified, a -// ReferenceGrant object is required in the referent namespace to allow that -// namespace's owner to accept the reference. See the ReferenceGrant -// documentation for details. -// -// -// -// When the BackendRef points to a Kubernetes Service, implementations SHOULD -// honor the appProtocol field if it is set for the target Service Port. -// -// Implementations supporting appProtocol SHOULD recognize the Kubernetes -// Standard Application Protocols defined in KEP-3726. -// -// If a Service appProtocol isn't specified, an implementation MAY infer the -// backend protocol through its own means. Implementations MAY infer the -// protocol from the Route type referring to the backend Service. -// -// If a Route is not able to send traffic to the backend using the specified -// protocol then the backend is considered invalid. Implementations MUST set the -// "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. -// -// -type HTTPBackendRef struct { - // BackendRef is a reference to a backend to forward matched requests to. - // - // A BackendRef can be invalid for the following reasons. In all cases, the - // implementation MUST ensure the `ResolvedRefs` Condition on the Route - // is set to `status: False`, with a Reason and Message that indicate - // what is the cause of the error. - // - // A BackendRef is invalid if: - // - // * It refers to an unknown or unsupported kind of resource. In this - // case, the Reason must be set to `InvalidKind` and Message of the - // Condition must explain which kind of resource is unknown or unsupported. - // - // * It refers to a resource that does not exist. In this case, the Reason must - // be set to `BackendNotFound` and the Message of the Condition must explain - // which resource does not exist. - // - // * It refers a resource in another namespace when the reference has not been - // explicitly allowed by a ReferenceGrant (or equivalent concept). In this - // case, the Reason must be set to `RefNotPermitted` and the Message of the - // Condition must explain which cross-namespace reference is not allowed. - // - // * It refers to a Kubernetes Service that has an incompatible appProtocol - // for the given Route type - // - // * The BackendTLSPolicy object is installed in the cluster, a BackendTLSPolicy - // is present that refers to the Service, and the implementation is unable - // to meet the requirement. At the time of writing, BackendTLSPolicy is - // experimental, but once it becomes standard, this will become a MUST - // requirement. - // - // Support: Core for Kubernetes Service - // - // Support: Implementation-specific for any other resource - // - // Support for weight: Core - // - // Support for Kubernetes Service appProtocol: Extended - // - // Support for BackendTLSPolicy: Experimental and ImplementationSpecific - // - // +optional - BackendRef `json:",inline"` - - // Filters defined at this level should be executed if and only if the - // request is being forwarded to the backend defined here. - // - // Support: Implementation-specific (For broader support of filters, use the - // Filters field in HTTPRouteRule.) - // - // +optional - // +kubebuilder:validation:MaxItems=16 - // +kubebuilder:validation:XValidation:message="May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both",rule="!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" - // +kubebuilder:validation:XValidation:message="May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both",rule="!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" - // +kubebuilder:validation:XValidation:message="RequestHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1" - // +kubebuilder:validation:XValidation:message="ResponseHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1" - // +kubebuilder:validation:XValidation:message="RequestRedirect filter cannot be repeated",rule="self.filter(f, f.type == 'RequestRedirect').size() <= 1" - // +kubebuilder:validation:XValidation:message="URLRewrite filter cannot be repeated",rule="self.filter(f, f.type == 'URLRewrite').size() <= 1" - Filters []HTTPRouteFilter `json:"filters,omitempty"` -} +// HTTPBackendRef defines how a HTTPRoute should forward an HTTP request. +// +k8s:deepcopy-gen=false +type HTTPBackendRef = v1.HTTPBackendRef // HTTPRouteStatus defines the observed state of HTTPRoute. -type HTTPRouteStatus struct { - RouteStatus `json:",inline"` -} +// +k8s:deepcopy-gen=false +type HTTPRouteStatus = v1.HTTPRouteStatus diff --git a/apis/v1beta1/object_reference_types.go b/apis/v1beta1/object_reference_types.go index 8ef008db0e..64a904e1e0 100644 --- a/apis/v1beta1/object_reference_types.go +++ b/apis/v1beta1/object_reference_types.go @@ -16,6 +16,8 @@ limitations under the License. package v1beta1 +import v1 "sigs.k8s.io/gateway-api/apis/v1" + // LocalObjectReference identifies an API object within the namespace of the // referrer. // The API object must be valid in the cluster; the Group and Kind must @@ -24,17 +26,8 @@ package v1beta1 // 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. -type LocalObjectReference struct { - // Group is the group of the referent. For example, "gateway.networking.k8s.io". - // When unspecified or empty string, core API group is inferred. - Group Group `json:"group"` - - // Kind is kind of the referent. For example "HTTPRoute" or "Service". - Kind Kind `json:"kind"` - - // Name is the name of the referent. - Name ObjectName `json:"name"` -} +// +k8s:deepcopy-gen=false +type LocalObjectReference = v1.LocalObjectReference // SecretObjectReference identifies an API object including its namespace, // defaulting to Secret. @@ -45,36 +38,8 @@ type LocalObjectReference struct { // 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. -type SecretObjectReference struct { - // Group is the group of the referent. For example, "gateway.networking.k8s.io". - // When unspecified or empty string, core API group is inferred. - // - // +optional - // +kubebuilder:default="" - Group *Group `json:"group"` - - // Kind is kind of the referent. For example "Secret". - // - // +optional - // +kubebuilder:default=Secret - Kind *Kind `json:"kind"` - - // Name is the name of the referent. - Name ObjectName `json:"name"` - - // Namespace is the namespace of the referenced object. When unspecified, the local - // namespace is inferred. - // - // Note that when a namespace different than the local namespace is specified, - // a ReferenceGrant object is required in the referent namespace to allow that - // namespace's owner to accept the reference. See the ReferenceGrant - // documentation for details. - // - // Support: Core - // - // +optional - Namespace *Namespace `json:"namespace,omitempty"` -} +// +k8s:deepcopy-gen=false +type SecretObjectReference = v1.SecretObjectReference // BackendObjectReference defines how an ObjectReference that is // specific to BackendRef. It includes a few additional fields and features @@ -91,57 +56,5 @@ type SecretObjectReference struct { // 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. -// -// +kubebuilder:validation:XValidation:message="Must have port for Service reference",rule="(size(self.group) == 0 && self.kind == 'Service') ? has(self.port) : true" -type BackendObjectReference struct { - // Group is the group of the referent. For example, "gateway.networking.k8s.io". - // When unspecified or empty string, core API group is inferred. - // - // +optional - // +kubebuilder:default="" - Group *Group `json:"group,omitempty"` - - // Kind is the Kubernetes resource kind of the referent. For example - // "Service". - // - // Defaults to "Service" when not specified. - // - // ExternalName services can refer to CNAME DNS records that may live - // outside of the cluster and as such are difficult to reason about in - // terms of conformance. They also may not be safe to forward to (see - // CVE-2021-25740 for more information). Implementations SHOULD NOT - // support ExternalName Services. - // - // Support: Core (Services with a type other than ExternalName) - // - // Support: Implementation-specific (Services with type ExternalName) - // - // +optional - // +kubebuilder:default=Service - Kind *Kind `json:"kind,omitempty"` - - // Name is the name of the referent. - Name ObjectName `json:"name"` - - // Namespace is the namespace of the backend. When unspecified, the local - // namespace is inferred. - // - // Note that when a namespace different than the local namespace is specified, - // a ReferenceGrant object is required in the referent namespace to allow that - // namespace's owner to accept the reference. See the ReferenceGrant - // documentation for details. - // - // Support: Core - // - // +optional - Namespace *Namespace `json:"namespace,omitempty"` - - // Port specifies the destination port number to use for this resource. - // Port is required when the referent is a Kubernetes Service. In this - // case, the port number is the service port number, not the target port. - // For other resources, destination port might be derived from the referent - // resource or this field. - // - // +optional - Port *PortNumber `json:"port,omitempty"` -} +// +k8s:deepcopy-gen=false +type BackendObjectReference = v1.BackendObjectReference diff --git a/apis/v1beta1/shared_types.go b/apis/v1beta1/shared_types.go index e7fe557241..7b60f3dd76 100644 --- a/apis/v1beta1/shared_types.go +++ b/apis/v1beta1/shared_types.go @@ -16,225 +16,34 @@ limitations under the License. package v1beta1 -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) +import v1 "sigs.k8s.io/gateway-api/apis/v1" // ParentReference identifies an API object (usually a Gateway) that can be considered -// a parent of this resource (usually a route). There are two kinds of parent resources -// with "Core" support: -// -// * Gateway (Gateway conformance profile) -// * Service (Mesh conformance profile, experimental, ClusterIP Services only) +// 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. // -// This API may be extended in the future to support additional kinds of parent -// resources. +// Note that there are specific rules for ParentRefs which cross namespace +// boundaries. Cross-namespace references are only valid if they are explicitly +// allowed by something in the namespace they are referring to. For example: +// Gateway has the AllowedRoutes field, and ReferenceGrant provides a +// generic way to enable any other kind of cross-namespace reference. // // 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. -type ParentReference struct { - // Group is the group of the referent. - // When unspecified, "gateway.networking.k8s.io" is inferred. - // To set the core API group (such as for a "Service" kind referent), - // Group must be explicitly set to "" (empty string). - // - // Support: Core - // - // +kubebuilder:default=gateway.networking.k8s.io - // +optional - Group *Group `json:"group,omitempty"` - - // Kind is kind of the referent. - // - // There are two kinds of parent resources with "Core" support: - // - // * Gateway (Gateway conformance profile) - // * Service (Mesh conformance profile, experimental, ClusterIP Services only) - // - // Support for other resources is Implementation-Specific. - // - // +kubebuilder:default=Gateway - // +optional - Kind *Kind `json:"kind,omitempty"` - - // Namespace is the namespace of the referent. When unspecified, this refers - // to the local namespace of the Route. - // - // Note that there are specific rules for ParentRefs which cross namespace - // boundaries. Cross-namespace references are only valid if they are explicitly - // allowed by something in the namespace they are referring to. For example: - // Gateway has the AllowedRoutes field, and ReferenceGrant provides a - // generic way to enable any other kind of cross-namespace reference. - // - // - // ParentRefs from a Route to a Service in the same namespace are "producer" - // routes, which apply default routing rules to inbound connections from - // any namespace to the Service. - // - // ParentRefs from a Route to a Service in a different namespace are - // "consumer" routes, and these routing rules are only applied to outbound - // connections originating from the same namespace as the Route, for which - // the intended destination of the connections are a Service targeted as a - // ParentRef of the Route. - // - // - // Support: Core - // - // +optional - Namespace *Namespace `json:"namespace,omitempty"` - - // Name is the name of the referent. - // - // Support: Core - Name ObjectName `json:"name"` - - // SectionName is the name of a section within the target resource. In the - // following resources, SectionName is interpreted as the following: - // - // * Gateway: Listener Name. When both Port (experimental) and SectionName - // are specified, the name and port of the selected listener must match - // both specified values. - // * Service: Port Name. When both Port (experimental) and SectionName - // are specified, the name and port of the selected listener must match - // both specified values. Note that attaching Routes to Services as Parents - // is part of experimental Mesh support and is not supported for any other - // purpose. - // - // Implementations MAY choose to support attaching Routes to other resources. - // If that is the case, they MUST clearly document how SectionName is - // interpreted. - // - // 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. - // - // Support: Core - // - // +optional - SectionName *SectionName `json:"sectionName,omitempty"` - - // Port is the network port this Route targets. It can be interpreted - // differently based on the type of parent resource. - // - // When the parent resource is a Gateway, this targets all listeners - // listening on the specified port that also support this kind of Route(and - // select this Route). It's not recommended to set `Port` unless the - // networking behaviors specified in a Route must apply to a specific port - // as opposed to a listener(s) whose port(s) may be changed. When both Port - // and SectionName are specified, the name and port of the selected listener - // must match both specified values. - // - // - // When the parent resource is a Service, this targets a specific port in the - // Service spec. When both Port (experimental) and SectionName are specified, - // the name and port of the selected port must match both specified values. - // - // - // Implementations MAY choose to support other parent resources. - // Implementations supporting other types of parent resources MUST clearly - // document how/if Port is interpreted. - // - // For the purpose of status, an attachment is considered successful as - // long as the parent resource accepts it partially. 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. - // - // Support: Extended - // - // +optional - // - Port *PortNumber `json:"port,omitempty"` -} +// +k8s:deepcopy-gen=false +type ParentReference = v1.ParentReference // CommonRouteSpec defines the common attributes that all Routes MUST include // within their spec. -type CommonRouteSpec struct { - // 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. For Services, that means the Service must either be in the same - // namespace for a "producer" route, or the mesh implementation must support - // and allow "consumer" routes for the referenced Service. ReferenceGrant is - // not applicable for governing ParentRefs to Services - it is not possible to - // create a "producer" route for a Service in a different namespace from the - // Route. - // - // There are two kinds of parent resources with "Core" support: - // - // * Gateway (Gateway conformance profile) - // - // * Service (Mesh conformance profile, experimental, ClusterIP Services only) - // - // This API may be extended in the future to support additional kinds of parent - // resources. - // - // ParentRefs must be _distinct_. This means either that: - // - // * They select different objects. If this is the case, then parentRef - // entries are distinct. In terms of fields, this means that the - // multi-part key defined by `group`, `kind`, `namespace`, and `name` must - // be unique across all parentRef entries in the Route. - // * They do not select different objects, but for each optional field used, - // each ParentRef that selects the same object must set the same set of - // optional fields to different values. If one ParentRef sets a - // combination of optional fields, all must set the same combination. - // - // Some examples: - // - // * If one ParentRef sets `sectionName`, all ParentRefs referencing the - // same object must also set `sectionName`. - // * If one ParentRef sets `port`, all ParentRefs referencing the same - // object must also set `port`. - // * If one ParentRef sets `sectionName` and `port`, all ParentRefs - // referencing the same object must also set `sectionName` and `port`. - // - // 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. - // - // Note that for ParentRefs that cross namespace boundaries, there are specific - // rules. Cross-namespace references are only valid if they are explicitly - // allowed by something in the namespace they are referring to. For example, - // Gateway has the AllowedRoutes field, and ReferenceGrant provides a - // generic way to enable other kinds of cross-namespace reference. - // - // - // ParentRefs from a Route to a Service in the same namespace are "producer" - // routes, which apply default routing rules to inbound connections from - // any namespace to the Service. - // - // ParentRefs from a Route to a Service in a different namespace are - // "consumer" routes, and these routing rules are only applied to outbound - // connections originating from the same namespace as the Route, for which - // the intended destination of the connections are a Service targeted as a - // ParentRef of the Route. - // - // - // +optional - // +kubebuilder:validation:MaxItems=32 - // - // - // - // - ParentRefs []ParentReference `json:"parentRefs,omitempty"` -} +// +k8s:deepcopy-gen=false +type CommonRouteSpec = v1.CommonRouteSpec // PortNumber defines a network port. // // +kubebuilder:validation:Minimum=1 // +kubebuilder:validation:Maximum=65535 -type PortNumber int32 +type PortNumber = v1.PortNumber // BackendRef defines how a Route should forward a request to a Kubernetes // resource. @@ -243,64 +52,20 @@ type PortNumber int32 // ReferenceGrant object is required in the referent namespace to allow that // namespace's owner to accept the reference. See the ReferenceGrant // documentation for details. -// -// -// -// When the BackendRef points to a Kubernetes Service, implementations SHOULD -// honor the appProtocol field if it is set for the target Service Port. -// -// Implementations supporting appProtocol SHOULD recognize the Kubernetes -// Standard Application Protocols defined in KEP-3726. -// -// If a Service appProtocol isn't specified, an implementation MAY infer the -// backend protocol through its own means. Implementations MAY infer the -// protocol from the Route type referring to the backend Service. -// -// If a Route is not able to send traffic to the backend using the specified -// protocol then the backend is considered invalid. Implementations MUST set the -// "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. -// -// -// -// Note that when the BackendTLSPolicy object is enabled by the implementation, -// there are some extra rules about validity to consider here. See the fields -// where this struct is used for more information about the exact behavior. -type BackendRef struct { - // BackendObjectReference references a Kubernetes object. - BackendObjectReference `json:",inline"` - - // 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. - // - // 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. - // - // Support for this field varies based on the context where used. - // - // +optional - // +kubebuilder:default=1 - // +kubebuilder:validation:Minimum=0 - // +kubebuilder:validation:Maximum=1000000 - Weight *int32 `json:"weight,omitempty"` -} +// +k8s:deepcopy-gen=false +type BackendRef = v1.BackendRef // RouteConditionType is a type of condition for a route. -type RouteConditionType string +type RouteConditionType = v1.RouteConditionType // RouteConditionReason is a reason for a route condition. -type RouteConditionReason string +type RouteConditionReason = v1.RouteConditionReason const ( // This condition indicates whether the route has been accepted or rejected // by a Gateway, and why. // - // Possible reasons for this condition to be True are: + // Possible reasons for this condition to be true are: // // * "Accepted" // @@ -308,7 +73,6 @@ const ( // // * "NotAllowedByListeners" // * "NoMatchingListenerHostname" - // * "NoMatchingParent" // * "UnsupportedValue" // // Possible reasons for this condition to be Unknown are: @@ -333,12 +97,6 @@ const ( // compatible Listeners whose Hostname matches the route RouteReasonNoMatchingListenerHostname RouteConditionReason = "NoMatchingListenerHostname" - // This reason is used with the "Accepted" condition when there are - // no matching Parents. In the case of Gateways, this can occur when - // a Route ParentRef specifies a Port and/or SectionName that does not - // match any Listeners in the Gateway. - RouteReasonNoMatchingParent RouteConditionReason = "NoMatchingParent" - // This reason is used with the "Accepted" condition when a value for an Enum // is not recognized. RouteReasonUnsupportedValue RouteConditionReason = "UnsupportedValue" @@ -347,26 +105,18 @@ const ( // reconciled the route. RouteReasonPending RouteConditionReason = "Pending" - // This reason is used with the "Accepted" condition when there - // are incompatible filters present on a route rule (for example if - // the URLRewrite and RequestRedirect are both present on an HTTPRoute). - RouteReasonIncompatibleFilters RouteConditionReason = "IncompatibleFilters" -) - -const ( // This condition indicates whether the controller was able to resolve all // the object references for the Route. // - // Possible reasons for this condition to be True are: + // Possible reasons for this condition to be true are: // // * "ResolvedRefs" // - // Possible reasons for this condition to be False are: + // Possible reasons for this condition to be false are: // // * "RefNotPermitted" // * "InvalidKind" // * "BackendNotFound" - // * "UnsupportedProtocol" // // Controllers may raise this condition with other reasons, // but should prefer to use the reasons listed above to improve @@ -391,120 +141,17 @@ const ( // This reason is used with the "ResolvedRefs" condition when one of the // Route's rules has a reference to a resource that does not exist. RouteReasonBackendNotFound RouteConditionReason = "BackendNotFound" - - // This reason is used with the "ResolvedRefs" condition when one of the - // Route's rules has a reference to a resource with an app protocol that - // is not supported by this implementation. - RouteReasonUnsupportedProtocol RouteConditionReason = "UnsupportedProtocol" -) - -const ( - // This condition indicates that the Route contains a combination of both - // valid and invalid rules. - // - // When this happens, implementations MUST take one of the following - // approaches: - // - // 1) Drop Rule(s): With this approach, implementations will drop the - // invalid Route Rule(s) until they are fully valid again. The message - // for this condition MUST start with the prefix "Dropped Rule" and - // include information about which Rules have been dropped. In this - // state, the "Accepted" condition MUST be set to "True" with the latest - // generation of the resource. - // 2) Fall Back: With this approach, implementations will fall back to the - // last known good state of the entire Route. The message for this - // condition MUST start with the prefix "Fall Back" and include - // information about why the current Rule(s) are invalid. To represent - // this, the "Accepted" condition MUST be set to "True" with the - // generation of the last known good state of the resource. - // - // Reverting to the last known good state should only be done by - // implementations that have a means of restoring that state if/when they - // are restarted. - // - // This condition MUST NOT be set if a Route is fully valid, fully invalid, - // or not accepted. By extension, that means that this condition MUST only - // be set when it is "True". - // - // Possible reasons for this condition to be True are: - // - // * "UnsupportedValue" - // - // Controllers may raise this condition with other reasons, but should - // prefer to use the reasons listed above to improve interoperability. - RouteConditionPartiallyInvalid RouteConditionType = "PartiallyInvalid" ) // RouteParentStatus describes the status of a route with respect to an // associated Parent. -type RouteParentStatus struct { - // ParentRef corresponds with a ParentRef in the spec that this - // RouteParentStatus struct describes the status of. - ParentRef ParentReference `json:"parentRef"` - - // 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). - // - // Controllers MUST populate this field when writing status. Controllers should ensure that - // entries to status populated with their ControllerName are cleaned up when they are no - // longer necessary. - 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 - // status conditions and listener status. - // - // 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. - // - // 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 "Accepted" condition may not be set - // due to lack of controller visibility, that includes when: - // - // * 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 controller does not have access to. - // - // +listType=map - // +listMapKey=type - // +kubebuilder:validation:MinItems=1 - // +kubebuilder:validation:MaxItems=8 - Conditions []metav1.Condition `json:"conditions,omitempty"` -} +// +k8s:deepcopy-gen=false +type RouteParentStatus = v1.RouteParentStatus // RouteStatus defines the common attributes that all Routes MUST include within // their status. -type RouteStatus struct { - // 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. - // - // 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. - // - // +kubebuilder:validation:MaxItems=32 - Parents []RouteParentStatus `json:"parents"` -} +// +k8s:deepcopy-gen=false +type RouteStatus = v1.RouteStatus // Hostname is the fully qualified domain name of a network host. This matches // the RFC 1123 definition of a hostname with 2 notable exceptions: @@ -524,7 +171,7 @@ type RouteStatus struct { // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=`^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` -type Hostname string +type Hostname = v1.Hostname // PreciseHostname is the fully qualified domain name of a network host. This // matches the RFC 1123 definition of a hostname with 1 notable exception that @@ -537,7 +184,7 @@ type Hostname string // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` -type PreciseHostname string +type PreciseHostname = v1.PreciseHostname // Group refers to a Kubernetes Group. It must either be an empty string or a // RFC 1123 subdomain. @@ -548,7 +195,7 @@ type PreciseHostname string // Valid values include: // // * "" - empty string implies core Kubernetes API group -// * "gateway.networking.k8s.io" +// * "networking.k8s.io" // * "foo.example.com" // // Invalid values include: @@ -557,7 +204,7 @@ type PreciseHostname string // // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=`^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` -type Group string +type Group = v1.Group // Kind refers to a Kubernetes Kind. // @@ -573,7 +220,7 @@ type Group string // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern=`^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` -type Kind string +type Kind = v1.Kind // ObjectName refers to the name of a Kubernetes object. // Object names can have a variety of forms, including RFC1123 subdomains, @@ -581,7 +228,7 @@ type Kind string // // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 -type ObjectName string +type ObjectName = v1.ObjectName // Namespace refers to a Kubernetes namespace. It must be a RFC 1123 label. // @@ -602,7 +249,7 @@ type ObjectName string // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 -type Namespace string +type Namespace = v1.Namespace // SectionName is the name of a section in a Kubernetes resource. // @@ -621,7 +268,7 @@ type Namespace string // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 -type SectionName string +type SectionName = v1.SectionName // GatewayController is the name of a Gateway API controller. It must be a // domain prefixed path. @@ -638,7 +285,7 @@ type SectionName string // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` -type GatewayController string +type GatewayController = v1.GatewayController // AnnotationKey is the key of an annotation in Gateway API. This is used for // validation of maps such as TLS options. This matches the Kubernetes @@ -660,7 +307,7 @@ type GatewayController string // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=`^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]/?)*$` -type AnnotationKey string +type AnnotationKey = v1.AnnotationKey // 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 @@ -669,7 +316,7 @@ type AnnotationKey string // // +kubebuilder:validation:MinLength=0 // +kubebuilder:validation:MaxLength=4096 -type AnnotationValue string +type AnnotationValue = v1.AnnotationValue // AddressType defines how a network address is represented as a text string. // This may take two possible forms: @@ -689,21 +336,11 @@ type AnnotationValue string // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=`^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` -type AddressType string - -// HeaderName is the name of a header or query parameter. -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=256 -// +kubebuilder:validation:Pattern=`^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$` -// +k8s:deepcopy-gen=false -type HeaderName string +type AddressType = v1.AddressType // Duration is a string value representing a duration in time. The format is as specified // in GEP-2257, a strict subset of the syntax parsed by Golang time.ParseDuration. -// -// +kubebuilder:validation:Pattern=`^([0-9]{1,5}(h|m|s|ms)){1,4}$` -type Duration string +type Duration = v1.Duration const ( // A textual representation of a numeric IP address. IPv4 diff --git a/apis/v1beta1/validation/gateway.go b/apis/v1beta1/validation/gateway.go index 3119efb2c0..cdc27930e4 100644 --- a/apis/v1beta1/validation/gateway.go +++ b/apis/v1beta1/validation/gateway.go @@ -24,25 +24,26 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) var ( // set of protocols for which we need to validate that hostname is empty protocolsHostnameInvalid = map[gatewayv1b1.ProtocolType]struct{}{ - gatewayv1b1.TCPProtocolType: {}, - gatewayv1b1.UDPProtocolType: {}, + gatewayv1.TCPProtocolType: {}, + gatewayv1.UDPProtocolType: {}, } // set of protocols for which TLSConfig shall not be present protocolsTLSInvalid = map[gatewayv1b1.ProtocolType]struct{}{ - gatewayv1b1.HTTPProtocolType: {}, - gatewayv1b1.UDPProtocolType: {}, - gatewayv1b1.TCPProtocolType: {}, + gatewayv1.HTTPProtocolType: {}, + gatewayv1.UDPProtocolType: {}, + gatewayv1.TCPProtocolType: {}, } // set of protocols for which TLSConfig must be set protocolsTLSRequired = map[gatewayv1b1.ProtocolType]struct{}{ - gatewayv1b1.HTTPSProtocolType: {}, - gatewayv1b1.TLSProtocolType: {}, + gatewayv1.HTTPSProtocolType: {}, + gatewayv1.TLSProtocolType: {}, } validHostnameAddress = `^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` @@ -120,7 +121,7 @@ func ValidateTLSCertificateRefs(listeners []gatewayv1b1.Listener, path *field.Pa var errs field.ErrorList for i, c := range listeners { if isProtocolInSubset(c.Protocol, protocolsTLSRequired) && c.TLS != nil { - if *c.TLS.Mode == gatewayv1b1.TLSModeTerminate && len(c.TLS.CertificateRefs) == 0 { + if *c.TLS.Mode == gatewayv1.TLSModeTerminate && len(c.TLS.CertificateRefs) == 0 { errs = append(errs, field.Forbidden(path.Index(i).Child("tls").Child("certificateRefs"), "should be set and not empty when TLSModeType is Terminate")) } } diff --git a/apis/v1beta1/validation/gateway_test.go b/apis/v1beta1/validation/gateway_test.go index 533c4e97f4..e6ff703fdf 100644 --- a/apis/v1beta1/validation/gateway_test.go +++ b/apis/v1beta1/validation/gateway_test.go @@ -23,6 +23,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/validation/field" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) @@ -56,7 +57,7 @@ func TestValidateGateway(t *testing.T) { }{ "tls config present with http protocol": { mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners[0].Protocol = gatewayv1b1.HTTPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPProtocolType gw.Spec.Listeners[0].TLS = &tlsConfig }, expectErrs: []field.Error{ @@ -70,7 +71,7 @@ func TestValidateGateway(t *testing.T) { }, "tls config present with tcp protocol": { mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners[0].Protocol = gatewayv1b1.TCPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.TCPProtocolType gw.Spec.Listeners[0].TLS = &tlsConfig }, expectErrs: []field.Error{ @@ -84,7 +85,7 @@ func TestValidateGateway(t *testing.T) { }, "tls config not set with https protocol": { mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners[0].Protocol = gatewayv1b1.HTTPSProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPSProtocolType }, expectErrs: []field.Error{ { @@ -97,7 +98,7 @@ func TestValidateGateway(t *testing.T) { }, "tls config not set with tls protocol": { mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners[0].Protocol = gatewayv1b1.TLSProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.TLSProtocolType }, expectErrs: []field.Error{ { @@ -110,19 +111,19 @@ func TestValidateGateway(t *testing.T) { }, "tls config not set with http protocol": { mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners[0].Protocol = gatewayv1b1.HTTPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPProtocolType }, expectErrs: nil, }, "tls config not set with tcp protocol": { mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners[0].Protocol = gatewayv1b1.TCPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.TCPProtocolType }, expectErrs: nil, }, "tls config not set with udp protocol": { mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners[0].Protocol = gatewayv1b1.UDPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.UDPProtocolType }, expectErrs: nil, }, @@ -130,7 +131,7 @@ func TestValidateGateway(t *testing.T) { mutate: func(gw *gatewayv1b1.Gateway) { hostname := gatewayv1b1.Hostname("foo.bar.com") gw.Spec.Listeners[0].Hostname = &hostname - gw.Spec.Listeners[0].Protocol = gatewayv1b1.TCPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.TCPProtocolType }, expectErrs: []field.Error{ { @@ -145,7 +146,7 @@ func TestValidateGateway(t *testing.T) { mutate: func(gw *gatewayv1b1.Gateway) { hostname := gatewayv1b1.Hostname("foo.bar.com") gw.Spec.Listeners[0].Hostname = &hostname - gw.Spec.Listeners[0].Protocol = gatewayv1b1.UDPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.UDPProtocolType }, expectErrs: []field.Error{ { @@ -159,8 +160,8 @@ func TestValidateGateway(t *testing.T) { "certificatedRefs not set with https protocol and TLS terminate mode": { mutate: func(gw *gatewayv1b1.Gateway) { hostname := gatewayv1b1.Hostname("foo.bar.com") - tlsMode := gatewayv1b1.TLSModeType("Terminate") - gw.Spec.Listeners[0].Protocol = gatewayv1b1.HTTPSProtocolType + tlsMode := gatewayv1.TLSModeType("Terminate") + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPSProtocolType gw.Spec.Listeners[0].Hostname = &hostname gw.Spec.Listeners[0].TLS = &tlsConfig gw.Spec.Listeners[0].TLS.Mode = &tlsMode @@ -177,8 +178,8 @@ func TestValidateGateway(t *testing.T) { "certificatedRefs not set with tls protocol and TLS terminate mode": { mutate: func(gw *gatewayv1b1.Gateway) { hostname := gatewayv1b1.Hostname("foo.bar.com") - tlsMode := gatewayv1b1.TLSModeType("Terminate") - gw.Spec.Listeners[0].Protocol = gatewayv1b1.TLSProtocolType + tlsMode := gatewayv1.TLSModeType("Terminate") + gw.Spec.Listeners[0].Protocol = gatewayv1.TLSProtocolType gw.Spec.Listeners[0].Hostname = &hostname gw.Spec.Listeners[0].TLS = &tlsConfig gw.Spec.Listeners[0].TLS.Mode = &tlsMode @@ -218,13 +219,13 @@ func TestValidateGateway(t *testing.T) { hostnameFoo := gatewayv1b1.Hostname("foo.com") gw.Spec.Listeners[0].Name = "foo" gw.Spec.Listeners[0].Hostname = &hostnameFoo - gw.Spec.Listeners[0].Protocol = gatewayv1b1.HTTPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPProtocolType gw.Spec.Listeners[0].Port = 80 gw.Spec.Listeners = append(gw.Spec.Listeners, gatewayv1b1.Listener{ Name: "bar", Hostname: &hostnameFoo, - Protocol: gatewayv1b1.HTTPProtocolType, + Protocol: gatewayv1.HTTPProtocolType, Port: 80, }, ) @@ -240,12 +241,12 @@ func TestValidateGateway(t *testing.T) { "combination of port and protocol are not unique for each listener when hostnames not set": { mutate: func(gw *gatewayv1b1.Gateway) { gw.Spec.Listeners[0].Name = "foo" - gw.Spec.Listeners[0].Protocol = gatewayv1b1.HTTPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPProtocolType gw.Spec.Listeners[0].Port = 80 gw.Spec.Listeners = append(gw.Spec.Listeners, gatewayv1b1.Listener{ Name: "bar", - Protocol: gatewayv1b1.HTTPProtocolType, + Protocol: gatewayv1.HTTPProtocolType, Port: 80, }, ) @@ -263,13 +264,13 @@ func TestValidateGateway(t *testing.T) { hostnameFoo := gatewayv1b1.Hostname("foo.com") gw.Spec.Listeners[0].Name = "foo" gw.Spec.Listeners[0].Hostname = &hostnameFoo - gw.Spec.Listeners[0].Protocol = gatewayv1b1.HTTPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPProtocolType gw.Spec.Listeners[0].Port = 80 gw.Spec.Listeners = append(gw.Spec.Listeners, gatewayv1b1.Listener{ Name: "bar", Hostname: &hostnameFoo, - Protocol: gatewayv1b1.HTTPProtocolType, + Protocol: gatewayv1.HTTPProtocolType, Port: 8080, }, ) @@ -282,13 +283,13 @@ func TestValidateGateway(t *testing.T) { hostnameBar := gatewayv1b1.Hostname("bar.com") gw.Spec.Listeners[0].Name = "foo" gw.Spec.Listeners[0].Hostname = &hostnameFoo - gw.Spec.Listeners[0].Protocol = gatewayv1b1.HTTPProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPProtocolType gw.Spec.Listeners[0].Port = 80 gw.Spec.Listeners = append(gw.Spec.Listeners, gatewayv1b1.Listener{ Name: "bar", Hostname: &hostnameBar, - Protocol: gatewayv1b1.HTTPProtocolType, + Protocol: gatewayv1.HTTPProtocolType, Port: 80, }, ) @@ -299,7 +300,7 @@ func TestValidateGateway(t *testing.T) { mutate: func(gw *gatewayv1b1.Gateway) { hostnameFoo := gatewayv1b1.Hostname("foo.com") tlsConfigFoo := tlsConfig - tlsModeFoo := gatewayv1b1.TLSModeType("Terminate") + tlsModeFoo := gatewayv1.TLSModeType("Terminate") tlsConfigFoo.Mode = &tlsModeFoo tlsConfigFoo.CertificateRefs = []gatewayv1b1.SecretObjectReference{ { @@ -308,14 +309,14 @@ func TestValidateGateway(t *testing.T) { } gw.Spec.Listeners[0].Name = "foo" gw.Spec.Listeners[0].Hostname = &hostnameFoo - gw.Spec.Listeners[0].Protocol = gatewayv1b1.HTTPSProtocolType + gw.Spec.Listeners[0].Protocol = gatewayv1.HTTPSProtocolType gw.Spec.Listeners[0].Port = 8000 gw.Spec.Listeners[0].TLS = &tlsConfigFoo gw.Spec.Listeners = append(gw.Spec.Listeners, gatewayv1b1.Listener{ Name: "bar", Hostname: &hostnameFoo, - Protocol: gatewayv1b1.TLSProtocolType, + Protocol: gatewayv1.TLSProtocolType, Port: 8000, TLS: &tlsConfigFoo, }, diff --git a/apis/v1beta1/validation/httproute.go b/apis/v1beta1/validation/httproute.go index a1c96b8722..d5cba86e6b 100644 --- a/apis/v1beta1/validation/httproute.go +++ b/apis/v1beta1/validation/httproute.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) @@ -32,8 +33,8 @@ var ( // repeatableHTTPRouteFilters are filter types that are allowed to be // repeated multiple times in a rule. repeatableHTTPRouteFilters = []gatewayv1b1.HTTPRouteFilterType{ - gatewayv1b1.HTTPRouteFilterExtensionRef, - gatewayv1b1.HTTPRouteFilterRequestMirror, + gatewayv1.HTTPRouteFilterExtensionRef, + gatewayv1.HTTPRouteFilterRequestMirror, } // Invalid path sequences and suffixes, primarily related to directory traversal @@ -89,7 +90,7 @@ func validateRequestRedirectFiltersWithBackendRefs(rule gatewayv1b1.HTTPRouteRul var errs field.ErrorList for _, filter := range rule.Filters { if filter.RequestRedirect != nil && len(rule.BackendRefs) > 0 { - errs = append(errs, field.Invalid(path.Child("filters"), gatewayv1b1.HTTPRouteFilterRequestRedirect, "RequestRedirect filter is not allowed with backendRefs")) + errs = append(errs, field.Invalid(path.Child("filters"), gatewayv1.HTTPRouteFilterRequestRedirect, "RequestRedirect filter is not allowed with backendRefs")) } } return errs @@ -144,8 +145,8 @@ func validateHTTPRouteFilters(filters []gatewayv1b1.HTTPRouteFilter, matches []g errs = append(errs, validateHTTPRouteFilterTypeMatchesValue(filter, path.Index(i))...) } - if counts[gatewayv1b1.HTTPRouteFilterRequestRedirect] > 0 && counts[gatewayv1b1.HTTPRouteFilterURLRewrite] > 0 { - errs = append(errs, field.Invalid(path.Child("filters"), gatewayv1b1.HTTPRouteFilterRequestRedirect, "may specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both")) + if counts[gatewayv1.HTTPRouteFilterRequestRedirect] > 0 && counts[gatewayv1.HTTPRouteFilterURLRewrite] > 0 { + errs = append(errs, field.Invalid(path.Child("filters"), gatewayv1.HTTPRouteFilterRequestRedirect, "may specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both")) } // repeatableHTTPRouteFilters filters can be used more than once @@ -174,7 +175,7 @@ func validateHTTPPathMatch(path *gatewayv1b1.HTTPPathMatch, fldPath *field.Path) } switch *path.Type { - case gatewayv1b1.PathMatchExact, gatewayv1b1.PathMatchPathPrefix: + case gatewayv1.PathMatchExact, gatewayv1.PathMatchPathPrefix: if !strings.HasPrefix(*path.Value, "/") { allErrs = append(allErrs, field.Invalid(fldPath.Child("value"), *path.Value, "must be an absolute path")) } @@ -201,9 +202,9 @@ func validateHTTPPathMatch(path *gatewayv1b1.HTTPPathMatch, fldPath *field.Path) fmt.Sprintf("must only contain valid characters (matching %s)", validPathCharacters))) } - case gatewayv1b1.PathMatchRegularExpression: + case gatewayv1.PathMatchRegularExpression: default: - pathTypes := []string{string(gatewayv1b1.PathMatchExact), string(gatewayv1b1.PathMatchPathPrefix), string(gatewayv1b1.PathMatchRegularExpression)} + pathTypes := []string{string(gatewayv1.PathMatchExact), string(gatewayv1.PathMatchPathPrefix), string(gatewayv1.PathMatchRegularExpression)} allErrs = append(allErrs, field.NotSupported(fldPath.Child("type"), *path.Type, pathTypes)) } return allErrs @@ -253,40 +254,40 @@ func validateHTTPQueryParamMatches(matches []gatewayv1b1.HTTPQueryParamMatch, pa // set for the specified filter type. func validateHTTPRouteFilterTypeMatchesValue(filter gatewayv1b1.HTTPRouteFilter, path *field.Path) field.ErrorList { var errs field.ErrorList - if filter.ExtensionRef != nil && filter.Type != gatewayv1b1.HTTPRouteFilterExtensionRef { + if filter.ExtensionRef != nil && filter.Type != gatewayv1.HTTPRouteFilterExtensionRef { errs = append(errs, field.Invalid(path, filter.ExtensionRef, "must be nil if the HTTPRouteFilter.Type is not ExtensionRef")) } - if filter.ExtensionRef == nil && filter.Type == gatewayv1b1.HTTPRouteFilterExtensionRef { + if filter.ExtensionRef == nil && filter.Type == gatewayv1.HTTPRouteFilterExtensionRef { errs = append(errs, field.Required(path, "filter.ExtensionRef must be specified for ExtensionRef HTTPRouteFilter.Type")) } - if filter.RequestHeaderModifier != nil && filter.Type != gatewayv1b1.HTTPRouteFilterRequestHeaderModifier { + if filter.RequestHeaderModifier != nil && filter.Type != gatewayv1.HTTPRouteFilterRequestHeaderModifier { errs = append(errs, field.Invalid(path, filter.RequestHeaderModifier, "must be nil if the HTTPRouteFilter.Type is not RequestHeaderModifier")) } - if filter.RequestHeaderModifier == nil && filter.Type == gatewayv1b1.HTTPRouteFilterRequestHeaderModifier { + if filter.RequestHeaderModifier == nil && filter.Type == gatewayv1.HTTPRouteFilterRequestHeaderModifier { errs = append(errs, field.Required(path, "filter.RequestHeaderModifier must be specified for RequestHeaderModifier HTTPRouteFilter.Type")) } - if filter.ResponseHeaderModifier != nil && filter.Type != gatewayv1b1.HTTPRouteFilterResponseHeaderModifier { + if filter.ResponseHeaderModifier != nil && filter.Type != gatewayv1.HTTPRouteFilterResponseHeaderModifier { errs = append(errs, field.Invalid(path, filter.ResponseHeaderModifier, "must be nil if the HTTPRouteFilter.Type is not ResponseHeaderModifier")) } - if filter.ResponseHeaderModifier == nil && filter.Type == gatewayv1b1.HTTPRouteFilterResponseHeaderModifier { + if filter.ResponseHeaderModifier == nil && filter.Type == gatewayv1.HTTPRouteFilterResponseHeaderModifier { errs = append(errs, field.Required(path, "filter.ResponseHeaderModifier must be specified for ResponseHeaderModifier HTTPRouteFilter.Type")) } - if filter.RequestMirror != nil && filter.Type != gatewayv1b1.HTTPRouteFilterRequestMirror { + if filter.RequestMirror != nil && filter.Type != gatewayv1.HTTPRouteFilterRequestMirror { errs = append(errs, field.Invalid(path, filter.RequestMirror, "must be nil if the HTTPRouteFilter.Type is not RequestMirror")) } - if filter.RequestMirror == nil && filter.Type == gatewayv1b1.HTTPRouteFilterRequestMirror { + if filter.RequestMirror == nil && filter.Type == gatewayv1.HTTPRouteFilterRequestMirror { errs = append(errs, field.Required(path, "filter.RequestMirror must be specified for RequestMirror HTTPRouteFilter.Type")) } - if filter.RequestRedirect != nil && filter.Type != gatewayv1b1.HTTPRouteFilterRequestRedirect { + if filter.RequestRedirect != nil && filter.Type != gatewayv1.HTTPRouteFilterRequestRedirect { errs = append(errs, field.Invalid(path, filter.RequestRedirect, "must be nil if the HTTPRouteFilter.Type is not RequestRedirect")) } - if filter.RequestRedirect == nil && filter.Type == gatewayv1b1.HTTPRouteFilterRequestRedirect { + if filter.RequestRedirect == nil && filter.Type == gatewayv1.HTTPRouteFilterRequestRedirect { errs = append(errs, field.Required(path, "filter.RequestRedirect must be specified for RequestRedirect HTTPRouteFilter.Type")) } - if filter.URLRewrite != nil && filter.Type != gatewayv1b1.HTTPRouteFilterURLRewrite { + if filter.URLRewrite != nil && filter.Type != gatewayv1.HTTPRouteFilterURLRewrite { errs = append(errs, field.Invalid(path, filter.URLRewrite, "must be nil if the HTTPRouteFilter.Type is not URLRewrite")) } - if filter.URLRewrite == nil && filter.Type == gatewayv1b1.HTTPRouteFilterURLRewrite { + if filter.URLRewrite == nil && filter.Type == gatewayv1.HTTPRouteFilterURLRewrite { errs = append(errs, field.Required(path, "filter.URLRewrite must be specified for URLRewrite HTTPRouteFilter.Type")) } return errs @@ -296,20 +297,20 @@ func validateHTTPRouteFilterTypeMatchesValue(filter gatewayv1b1.HTTPRouteFilter, // path modifier. func validateHTTPPathModifier(modifier gatewayv1b1.HTTPPathModifier, matches []gatewayv1b1.HTTPRouteMatch, path *field.Path) field.ErrorList { var errs field.ErrorList - if modifier.ReplaceFullPath != nil && modifier.Type != gatewayv1b1.FullPathHTTPPathModifier { + if modifier.ReplaceFullPath != nil && modifier.Type != gatewayv1.FullPathHTTPPathModifier { errs = append(errs, field.Invalid(path, modifier.ReplaceFullPath, "must be nil if the HTTPRouteFilter.Type is not ReplaceFullPath")) } - if modifier.ReplaceFullPath == nil && modifier.Type == gatewayv1b1.FullPathHTTPPathModifier { + if modifier.ReplaceFullPath == nil && modifier.Type == gatewayv1.FullPathHTTPPathModifier { errs = append(errs, field.Invalid(path, modifier.ReplaceFullPath, "must not be nil if the HTTPRouteFilter.Type is ReplaceFullPath")) } - if modifier.ReplacePrefixMatch != nil && modifier.Type != gatewayv1b1.PrefixMatchHTTPPathModifier { + if modifier.ReplacePrefixMatch != nil && modifier.Type != gatewayv1.PrefixMatchHTTPPathModifier { errs = append(errs, field.Invalid(path, modifier.ReplacePrefixMatch, "must be nil if the HTTPRouteFilter.Type is not ReplacePrefixMatch")) } - if modifier.ReplacePrefixMatch == nil && modifier.Type == gatewayv1b1.PrefixMatchHTTPPathModifier { + if modifier.ReplacePrefixMatch == nil && modifier.Type == gatewayv1.PrefixMatchHTTPPathModifier { errs = append(errs, field.Invalid(path, modifier.ReplacePrefixMatch, "must not be nil if the HTTPRouteFilter.Type is ReplacePrefixMatch")) } - if modifier.Type == gatewayv1b1.PrefixMatchHTTPPathModifier && modifier.ReplacePrefixMatch != nil { + if modifier.Type == gatewayv1.PrefixMatchHTTPPathModifier && modifier.ReplacePrefixMatch != nil { if !hasExactlyOnePrefixMatch(matches) { errs = append(errs, field.Invalid(path, modifier.ReplacePrefixMatch, "exactly one PathPrefix match must be specified to use this path modifier")) } @@ -373,7 +374,7 @@ func hasExactlyOnePrefixMatch(matches []gatewayv1b1.HTTPRouteMatch) bool { return false } pathMatchType := matches[0].Path.Type - if *pathMatchType != gatewayv1b1.PathMatchPathPrefix { + if *pathMatchType != gatewayv1.PathMatchPathPrefix { return false } diff --git a/apis/v1beta1/validation/httproute_test.go b/apis/v1beta1/validation/httproute_test.go index ca29f0b067..f3ed685cbf 100644 --- a/apis/v1beta1/validation/httproute_test.go +++ b/apis/v1beta1/validation/httproute_test.go @@ -23,12 +23,13 @@ import ( "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/util/validation/field" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) func TestValidateHTTPRoute(t *testing.T) { testService := gatewayv1b1.ObjectName("test-service") - pathPrefixMatchType := gatewayv1b1.PathMatchPathPrefix + pathPrefixMatchType := gatewayv1.PathMatchPathPrefix tests := []struct { name string @@ -75,7 +76,7 @@ func TestValidateHTTPRoute(t *testing.T) { }, Filters: []gatewayv1b1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{ BackendRef: gatewayv1b1.BackendObjectReference{ Name: testService, @@ -101,19 +102,19 @@ func TestValidateHTTPRoute(t *testing.T) { }, Filters: []gatewayv1b1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, }, { - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("bar"), }, }, @@ -136,7 +137,7 @@ func TestValidateHTTPRoute(t *testing.T) { }, Filters: []gatewayv1b1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Set: []gatewayv1b1.HTTPHeader{ { @@ -147,7 +148,7 @@ func TestValidateHTTPRoute(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{ BackendRef: gatewayv1b1.BackendObjectReference{ Name: testService, @@ -156,7 +157,7 @@ func TestValidateHTTPRoute(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Add: []gatewayv1b1.HTTPHeader{ { @@ -184,7 +185,7 @@ func TestValidateHTTPRoute(t *testing.T) { }, Filters: []gatewayv1b1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Set: []gatewayv1b1.HTTPHeader{ { @@ -195,7 +196,7 @@ func TestValidateHTTPRoute(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Add: []gatewayv1b1.HTTPHeader{ { @@ -206,7 +207,7 @@ func TestValidateHTTPRoute(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterResponseHeaderModifier, + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, ResponseHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Add: []gatewayv1b1.HTTPHeader{ { @@ -217,7 +218,7 @@ func TestValidateHTTPRoute(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterResponseHeaderModifier, + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, ResponseHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Set: []gatewayv1b1.HTTPHeader{ { @@ -245,7 +246,7 @@ func TestValidateHTTPRoute(t *testing.T) { }, Filters: []gatewayv1b1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Set: []gatewayv1b1.HTTPHeader{ { @@ -256,7 +257,7 @@ func TestValidateHTTPRoute(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{ BackendRef: gatewayv1b1.BackendObjectReference{ Name: testService, @@ -295,10 +296,10 @@ func TestValidateHTTPRoute(t *testing.T) { { Filters: []gatewayv1b1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.FullPathHTTPPathModifier, + Type: gatewayv1.FullPathHTTPPathModifier, ReplaceFullPath: ptrTo("foo"), }, }, @@ -311,10 +312,10 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 2, rules: []gatewayv1b1.HTTPRouteRule{{ Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplaceFullPath: ptrTo("foo"), }, }, @@ -331,10 +332,10 @@ func TestValidateHTTPRoute(t *testing.T) { }, }}, Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -345,10 +346,10 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 1, rules: []gatewayv1b1.HTTPRouteRule{{ Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -370,10 +371,10 @@ func TestValidateHTTPRoute(t *testing.T) { }, }}, Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -384,10 +385,10 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 2, rules: []gatewayv1b1.HTTPRouteRule{{ Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.FullPathHTTPPathModifier, + Type: gatewayv1.FullPathHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -398,18 +399,18 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 3, rules: []gatewayv1b1.HTTPRouteRule{{ Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -420,33 +421,33 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 2, rules: []gatewayv1b1.HTTPRouteRule{{ Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Add: []gatewayv1b1.HTTPHeader{ { - Name: gatewayv1b1.HTTPHeaderName("x-fruit"), + Name: gatewayv1.HTTPHeaderName("x-fruit"), Value: "apple", }, { - Name: gatewayv1b1.HTTPHeaderName("x-vegetable"), + Name: gatewayv1.HTTPHeaderName("x-vegetable"), Value: "carrot", }, { - Name: gatewayv1b1.HTTPHeaderName("x-grain"), + Name: gatewayv1.HTTPHeaderName("x-grain"), Value: "rye", }, }, Set: []gatewayv1b1.HTTPHeader{ { - Name: gatewayv1b1.HTTPHeaderName("x-fruit"), + Name: gatewayv1.HTTPHeaderName("x-fruit"), Value: "watermelon", }, { - Name: gatewayv1b1.HTTPHeaderName("x-grain"), + Name: gatewayv1.HTTPHeaderName("x-grain"), Value: "wheat", }, { - Name: gatewayv1b1.HTTPHeaderName("x-spice"), + Name: gatewayv1.HTTPHeaderName("x-spice"), Value: "coriander", }, }, @@ -458,17 +459,17 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 1, rules: []gatewayv1b1.HTTPRouteRule{{ Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Add: []gatewayv1b1.HTTPHeader{ { - Name: gatewayv1b1.HTTPHeaderName("x-fruit"), + Name: gatewayv1.HTTPHeaderName("x-fruit"), Value: "apple", }, }, Set: []gatewayv1b1.HTTPHeader{ { - Name: gatewayv1b1.HTTPHeaderName("X-Fruit"), + Name: gatewayv1.HTTPHeaderName("X-Fruit"), Value: "watermelon", }, }, @@ -480,15 +481,15 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 1, rules: []gatewayv1b1.HTTPRouteRule{{ Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Add: []gatewayv1b1.HTTPHeader{ { - Name: gatewayv1b1.HTTPHeaderName("x-fruit"), + Name: gatewayv1.HTTPHeaderName("x-fruit"), Value: "apple", }, { - Name: gatewayv1b1.HTTPHeaderName("x-fruit"), + Name: gatewayv1.HTTPHeaderName("x-fruit"), Value: "plum", }, }, @@ -500,25 +501,25 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 0, rules: []gatewayv1b1.HTTPRouteRule{{ Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Add: []gatewayv1b1.HTTPHeader{ { - Name: gatewayv1b1.HTTPHeaderName("x-vegetable"), + Name: gatewayv1.HTTPHeaderName("x-vegetable"), Value: "carrot", }, { - Name: gatewayv1b1.HTTPHeaderName("x-grain"), + Name: gatewayv1.HTTPHeaderName("x-grain"), Value: "rye", }, }, Set: []gatewayv1b1.HTTPHeader{ { - Name: gatewayv1b1.HTTPHeaderName("x-fruit"), + Name: gatewayv1.HTTPHeaderName("x-fruit"), Value: "watermelon", }, { - Name: gatewayv1b1.HTTPHeaderName("x-spice"), + Name: gatewayv1.HTTPHeaderName("x-spice"), Value: "coriander", }, }, @@ -530,14 +531,14 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 1, rules: []gatewayv1b1.HTTPRouteRule{{ Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterResponseHeaderModifier, + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, ResponseHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Add: []gatewayv1b1.HTTPHeader{{ - Name: gatewayv1b1.HTTPHeaderName("x-example"), + Name: gatewayv1.HTTPHeaderName("x-example"), Value: "blueberry", }}, Set: []gatewayv1b1.HTTPHeader{{ - Name: gatewayv1b1.HTTPHeaderName("x-example"), + Name: gatewayv1.HTTPHeaderName("x-example"), Value: "turnip", }}, }, @@ -548,14 +549,14 @@ func TestValidateHTTPRoute(t *testing.T) { errCount: 0, rules: []gatewayv1b1.HTTPRouteRule{{ Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterResponseHeaderModifier, + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, ResponseHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Add: []gatewayv1b1.HTTPHeader{{ - Name: gatewayv1b1.HTTPHeaderName("x-example"), + Name: gatewayv1.HTTPHeaderName("x-example"), Value: "blueberry", }}, Set: []gatewayv1b1.HTTPHeader{{ - Name: gatewayv1b1.HTTPHeaderName("x-different"), + Name: gatewayv1.HTTPHeaderName("x-different"), Value: "turnip", }}, }, @@ -597,7 +598,7 @@ func TestValidateHTTPBackendUniqueFilters(t *testing.T) { }, Filters: []gatewayv1b1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{ BackendRef: gatewayv1b1.BackendObjectReference{ Name: testService, @@ -623,7 +624,7 @@ func TestValidateHTTPBackendUniqueFilters(t *testing.T) { }, Filters: []gatewayv1b1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{ BackendRef: gatewayv1b1.BackendObjectReference{ Name: testService, @@ -632,7 +633,7 @@ func TestValidateHTTPBackendUniqueFilters(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{ BackendRef: gatewayv1b1.BackendObjectReference{ Name: specialService, @@ -962,7 +963,7 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { }{{ name: "valid HTTPRouteFilterRequestHeaderModifier route filter", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ Set: []gatewayv1b1.HTTPHeader{{Name: "name"}}, Add: []gatewayv1b1.HTTPHeader{{Name: "add"}}, @@ -973,20 +974,20 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { }, { name: "invalid HTTPRouteFilterRequestHeaderModifier type filter with non-matching field", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{}, }, errCount: 2, }, { name: "invalid HTTPRouteFilterRequestHeaderModifier type filter with empty value field", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, }, errCount: 1, }, { name: "valid HTTPRouteFilterRequestMirror route filter", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{BackendRef: gatewayv1b1.BackendObjectReference{ Group: new(gatewayv1b1.Group), Kind: new(gatewayv1b1.Kind), @@ -999,20 +1000,20 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { }, { name: "invalid HTTPRouteFilterRequestMirror type filter with non-matching field", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{}, }, errCount: 2, }, { name: "invalid HTTPRouteFilterRequestMirror type filter with empty value field", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + Type: gatewayv1.HTTPRouteFilterRequestMirror, }, errCount: 1, }, { name: "valid HTTPRouteFilterRequestRedirect route filter", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ Scheme: new(string), Hostname: new(gatewayv1b1.PreciseHostname), @@ -1025,20 +1026,20 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { }, { name: "invalid HTTPRouteFilterRequestRedirect type filter with non-matching field", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{}, }, errCount: 2, }, { name: "invalid HTTPRouteFilterRequestRedirect type filter with empty value field", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, }, errCount: 1, }, { name: "valid HTTPRouteFilterExtensionRef filter", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterExtensionRef, + Type: gatewayv1.HTTPRouteFilterExtensionRef, ExtensionRef: &gatewayv1b1.LocalObjectReference{ Group: "group", Kind: "kind", @@ -1049,20 +1050,20 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { }, { name: "invalid HTTPRouteFilterExtensionRef type filter with non-matching field", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterExtensionRef, + Type: gatewayv1.HTTPRouteFilterExtensionRef, RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{}, }, errCount: 2, }, { name: "invalid HTTPRouteFilterExtensionRef type filter with empty value field", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterExtensionRef, + Type: gatewayv1.HTTPRouteFilterExtensionRef, }, errCount: 1, }, { name: "valid HTTPRouteFilterURLRewrite route filter", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ Hostname: new(gatewayv1b1.PreciseHostname), Path: &gatewayv1b1.HTTPPathModifier{}, @@ -1072,14 +1073,14 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { }, { name: "invalid HTTPRouteFilterURLRewrite type filter with non-matching field", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{}, }, errCount: 2, }, { name: "invalid HTTPRouteFilterURLRewrite type filter with empty value field", routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + Type: gatewayv1.HTTPRouteFilterURLRewrite, }, errCount: 1, }, { @@ -1127,7 +1128,7 @@ func TestValidateRequestRedirectFiltersWithNoBackendRef(t *testing.T) { { Filters: []gatewayv1b1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ Scheme: ptrTo("https"), StatusCode: ptrTo(301), @@ -1153,7 +1154,7 @@ func TestValidateRequestRedirectFiltersWithNoBackendRef(t *testing.T) { { Filters: []gatewayv1b1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ Scheme: ptrTo("https"), StatusCode: ptrTo(301), diff --git a/apis/v1beta1/zz_generated.deepcopy.go b/apis/v1beta1/zz_generated.deepcopy.go index f34200da0c..53dd02b677 100644 --- a/apis/v1beta1/zz_generated.deepcopy.go +++ b/apis/v1beta1/zz_generated.deepcopy.go @@ -21,115 +21,10 @@ limitations under the License. package v1beta1 import ( - "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/gateway-api/apis/v1" ) -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AllowedRoutes) DeepCopyInto(out *AllowedRoutes) { - *out = *in - if in.Namespaces != nil { - in, out := &in.Namespaces, &out.Namespaces - *out = new(RouteNamespaces) - (*in).DeepCopyInto(*out) - } - if in.Kinds != nil { - in, out := &in.Kinds, &out.Kinds - *out = make([]RouteGroupKind, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllowedRoutes. -func (in *AllowedRoutes) DeepCopy() *AllowedRoutes { - if in == nil { - return nil - } - out := new(AllowedRoutes) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BackendObjectReference) DeepCopyInto(out *BackendObjectReference) { - *out = *in - if in.Group != nil { - in, out := &in.Group, &out.Group - *out = new(Group) - **out = **in - } - if in.Kind != nil { - in, out := &in.Kind, &out.Kind - *out = new(Kind) - **out = **in - } - if in.Namespace != nil { - in, out := &in.Namespace, &out.Namespace - *out = new(Namespace) - **out = **in - } - if in.Port != nil { - in, out := &in.Port, &out.Port - *out = new(PortNumber) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendObjectReference. -func (in *BackendObjectReference) DeepCopy() *BackendObjectReference { - if in == nil { - return nil - } - out := new(BackendObjectReference) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BackendRef) DeepCopyInto(out *BackendRef) { - *out = *in - in.BackendObjectReference.DeepCopyInto(&out.BackendObjectReference) - if in.Weight != nil { - in, out := &in.Weight, &out.Weight - *out = new(int32) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendRef. -func (in *BackendRef) DeepCopy() *BackendRef { - if in == nil { - return nil - } - out := new(BackendRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CommonRouteSpec) DeepCopyInto(out *CommonRouteSpec) { - *out = *in - if in.ParentRefs != nil { - in, out := &in.ParentRefs, &out.ParentRefs - *out = make([]ParentReference, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonRouteSpec. -func (in *CommonRouteSpec) DeepCopy() *CommonRouteSpec { - if in == nil { - return nil - } - out := new(CommonRouteSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Gateway) DeepCopyInto(out *Gateway) { *out = *in @@ -157,26 +52,6 @@ func (in *Gateway) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayAddress) DeepCopyInto(out *GatewayAddress) { - *out = *in - if in.Type != nil { - in, out := &in.Type, &out.Type - *out = new(AddressType) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayAddress. -func (in *GatewayAddress) DeepCopy() *GatewayAddress { - if in == nil { - return nil - } - out := new(GatewayAddress) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GatewayClass) DeepCopyInto(out *GatewayClass) { *out = *in @@ -236,87 +111,6 @@ func (in *GatewayClassList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassSpec) DeepCopyInto(out *GatewayClassSpec) { - *out = *in - if in.ParametersRef != nil { - in, out := &in.ParametersRef, &out.ParametersRef - *out = new(ParametersReference) - (*in).DeepCopyInto(*out) - } - if in.Description != nil { - in, out := &in.Description, &out.Description - *out = new(string) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassSpec. -func (in *GatewayClassSpec) DeepCopy() *GatewayClassSpec { - if in == nil { - return nil - } - out := new(GatewayClassSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassStatus) DeepCopyInto(out *GatewayClassStatus) { - *out = *in - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.SupportedFeatures != nil { - in, out := &in.SupportedFeatures, &out.SupportedFeatures - *out = make([]SupportedFeature, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassStatus. -func (in *GatewayClassStatus) DeepCopy() *GatewayClassStatus { - if in == nil { - return nil - } - out := new(GatewayClassStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayInfrastructure) DeepCopyInto(out *GatewayInfrastructure) { - *out = *in - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make(map[AnnotationKey]AnnotationValue, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Annotations != nil { - in, out := &in.Annotations, &out.Annotations - *out = make(map[AnnotationKey]AnnotationValue, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayInfrastructure. -func (in *GatewayInfrastructure) DeepCopy() *GatewayInfrastructure { - if in == nil { - return nil - } - out := new(GatewayInfrastructure) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GatewayList) DeepCopyInto(out *GatewayList) { *out = *in @@ -350,863 +144,176 @@ func (in *GatewayList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewaySpec) DeepCopyInto(out *GatewaySpec) { +func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { *out = *in - if in.Listeners != nil { - in, out := &in.Listeners, &out.Listeners - *out = make([]Listener, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Addresses != nil { - in, out := &in.Addresses, &out.Addresses - *out = make([]GatewayAddress, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - in.Infrastructure.DeepCopyInto(&out.Infrastructure) + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewaySpec. -func (in *GatewaySpec) DeepCopy() *GatewaySpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRoute. +func (in *HTTPRoute) DeepCopy() *HTTPRoute { if in == nil { return nil } - out := new(GatewaySpec) + out := new(HTTPRoute) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HTTPRoute) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayStatus) DeepCopyInto(out *GatewayStatus) { +func (in *HTTPRouteList) DeepCopyInto(out *HTTPRouteList) { *out = *in - if in.Addresses != nil { - in, out := &in.Addresses, &out.Addresses - *out = make([]GatewayStatusAddress, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Listeners != nil { - in, out := &in.Listeners, &out.Listeners - *out = make([]ListenerStatus, len(*in)) + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]HTTPRoute, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayStatus. -func (in *GatewayStatus) DeepCopy() *GatewayStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteList. +func (in *HTTPRouteList) DeepCopy() *HTTPRouteList { if in == nil { return nil } - out := new(GatewayStatus) + out := new(HTTPRouteList) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HTTPRouteList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayStatusAddress) DeepCopyInto(out *GatewayStatusAddress) { +func (in *ReferenceGrant) DeepCopyInto(out *ReferenceGrant) { *out = *in - if in.Type != nil { - in, out := &in.Type, &out.Type - *out = new(AddressType) - **out = **in - } + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayStatusAddress. -func (in *GatewayStatusAddress) DeepCopy() *GatewayStatusAddress { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrant. +func (in *ReferenceGrant) DeepCopy() *ReferenceGrant { if in == nil { return nil } - out := new(GatewayStatusAddress) + out := new(ReferenceGrant) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ReferenceGrant) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayTLSConfig) DeepCopyInto(out *GatewayTLSConfig) { +func (in *ReferenceGrantFrom) DeepCopyInto(out *ReferenceGrantFrom) { *out = *in - if in.Mode != nil { - in, out := &in.Mode, &out.Mode - *out = new(TLSModeType) - **out = **in - } - if in.CertificateRefs != nil { - in, out := &in.CertificateRefs, &out.CertificateRefs - *out = make([]SecretObjectReference, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Options != nil { - in, out := &in.Options, &out.Options - *out = make(map[AnnotationKey]AnnotationValue, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayTLSConfig. -func (in *GatewayTLSConfig) DeepCopy() *GatewayTLSConfig { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrantFrom. +func (in *ReferenceGrantFrom) DeepCopy() *ReferenceGrantFrom { if in == nil { return nil } - out := new(GatewayTLSConfig) + out := new(ReferenceGrantFrom) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPBackendRef) DeepCopyInto(out *HTTPBackendRef) { +func (in *ReferenceGrantList) DeepCopyInto(out *ReferenceGrantList) { *out = *in - in.BackendRef.DeepCopyInto(&out.BackendRef) - if in.Filters != nil { - in, out := &in.Filters, &out.Filters - *out = make([]HTTPRouteFilter, len(*in)) + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ReferenceGrant, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPBackendRef. -func (in *HTTPBackendRef) DeepCopy() *HTTPBackendRef { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrantList. +func (in *ReferenceGrantList) DeepCopy() *ReferenceGrantList { if in == nil { return nil } - out := new(HTTPBackendRef) + out := new(ReferenceGrantList) in.DeepCopyInto(out) return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPHeader) DeepCopyInto(out *HTTPHeader) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeader. -func (in *HTTPHeader) DeepCopy() *HTTPHeader { - if in == nil { - return nil +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ReferenceGrantList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c } - out := new(HTTPHeader) - in.DeepCopyInto(out) - return out + return nil } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPHeaderFilter) DeepCopyInto(out *HTTPHeaderFilter) { +func (in *ReferenceGrantSpec) DeepCopyInto(out *ReferenceGrantSpec) { *out = *in - if in.Set != nil { - in, out := &in.Set, &out.Set - *out = make([]HTTPHeader, len(*in)) - copy(*out, *in) - } - if in.Add != nil { - in, out := &in.Add, &out.Add - *out = make([]HTTPHeader, len(*in)) + if in.From != nil { + in, out := &in.From, &out.From + *out = make([]ReferenceGrantFrom, len(*in)) copy(*out, *in) } - if in.Remove != nil { - in, out := &in.Remove, &out.Remove - *out = make([]string, len(*in)) - copy(*out, *in) + if in.To != nil { + in, out := &in.To, &out.To + *out = make([]ReferenceGrantTo, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeaderFilter. -func (in *HTTPHeaderFilter) DeepCopy() *HTTPHeaderFilter { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrantSpec. +func (in *ReferenceGrantSpec) DeepCopy() *ReferenceGrantSpec { if in == nil { return nil } - out := new(HTTPHeaderFilter) + out := new(ReferenceGrantSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPHeaderMatch) DeepCopyInto(out *HTTPHeaderMatch) { +func (in *ReferenceGrantTo) DeepCopyInto(out *ReferenceGrantTo) { *out = *in - if in.Type != nil { - in, out := &in.Type, &out.Type - *out = new(HeaderMatchType) + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(v1.ObjectName) **out = **in } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeaderMatch. -func (in *HTTPHeaderMatch) DeepCopy() *HTTPHeaderMatch { - if in == nil { - return nil - } - out := new(HTTPHeaderMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPPathMatch) DeepCopyInto(out *HTTPPathMatch) { - *out = *in - if in.Type != nil { - in, out := &in.Type, &out.Type - *out = new(PathMatchType) - **out = **in - } - if in.Value != nil { - in, out := &in.Value, &out.Value - *out = new(string) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPPathMatch. -func (in *HTTPPathMatch) DeepCopy() *HTTPPathMatch { - if in == nil { - return nil - } - out := new(HTTPPathMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPPathModifier) DeepCopyInto(out *HTTPPathModifier) { - *out = *in - if in.ReplaceFullPath != nil { - in, out := &in.ReplaceFullPath, &out.ReplaceFullPath - *out = new(string) - **out = **in - } - if in.ReplacePrefixMatch != nil { - in, out := &in.ReplacePrefixMatch, &out.ReplacePrefixMatch - *out = new(string) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPPathModifier. -func (in *HTTPPathModifier) DeepCopy() *HTTPPathModifier { - if in == nil { - return nil - } - out := new(HTTPPathModifier) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPQueryParamMatch) DeepCopyInto(out *HTTPQueryParamMatch) { - *out = *in - if in.Type != nil { - in, out := &in.Type, &out.Type - *out = new(QueryParamMatchType) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPQueryParamMatch. -func (in *HTTPQueryParamMatch) DeepCopy() *HTTPQueryParamMatch { - if in == nil { - return nil - } - out := new(HTTPQueryParamMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPRequestMirrorFilter) DeepCopyInto(out *HTTPRequestMirrorFilter) { - *out = *in - in.BackendRef.DeepCopyInto(&out.BackendRef) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRequestMirrorFilter. -func (in *HTTPRequestMirrorFilter) DeepCopy() *HTTPRequestMirrorFilter { - if in == nil { - return nil - } - out := new(HTTPRequestMirrorFilter) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPRequestRedirectFilter) DeepCopyInto(out *HTTPRequestRedirectFilter) { - *out = *in - if in.Scheme != nil { - in, out := &in.Scheme, &out.Scheme - *out = new(string) - **out = **in - } - if in.Hostname != nil { - in, out := &in.Hostname, &out.Hostname - *out = new(PreciseHostname) - **out = **in - } - if in.Path != nil { - in, out := &in.Path, &out.Path - *out = new(HTTPPathModifier) - (*in).DeepCopyInto(*out) - } - if in.Port != nil { - in, out := &in.Port, &out.Port - *out = new(PortNumber) - **out = **in - } - if in.StatusCode != nil { - in, out := &in.StatusCode, &out.StatusCode - *out = new(int) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRequestRedirectFilter. -func (in *HTTPRequestRedirectFilter) DeepCopy() *HTTPRequestRedirectFilter { - if in == nil { - return nil - } - out := new(HTTPRequestRedirectFilter) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRoute. -func (in *HTTPRoute) DeepCopy() *HTTPRoute { - if in == nil { - return nil - } - out := new(HTTPRoute) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *HTTPRoute) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPRouteFilter) DeepCopyInto(out *HTTPRouteFilter) { - *out = *in - if in.RequestHeaderModifier != nil { - in, out := &in.RequestHeaderModifier, &out.RequestHeaderModifier - *out = new(HTTPHeaderFilter) - (*in).DeepCopyInto(*out) - } - if in.ResponseHeaderModifier != nil { - in, out := &in.ResponseHeaderModifier, &out.ResponseHeaderModifier - *out = new(HTTPHeaderFilter) - (*in).DeepCopyInto(*out) - } - if in.RequestMirror != nil { - in, out := &in.RequestMirror, &out.RequestMirror - *out = new(HTTPRequestMirrorFilter) - (*in).DeepCopyInto(*out) - } - if in.RequestRedirect != nil { - in, out := &in.RequestRedirect, &out.RequestRedirect - *out = new(HTTPRequestRedirectFilter) - (*in).DeepCopyInto(*out) - } - if in.URLRewrite != nil { - in, out := &in.URLRewrite, &out.URLRewrite - *out = new(HTTPURLRewriteFilter) - (*in).DeepCopyInto(*out) - } - if in.ExtensionRef != nil { - in, out := &in.ExtensionRef, &out.ExtensionRef - *out = new(LocalObjectReference) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteFilter. -func (in *HTTPRouteFilter) DeepCopy() *HTTPRouteFilter { - if in == nil { - return nil - } - out := new(HTTPRouteFilter) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPRouteList) DeepCopyInto(out *HTTPRouteList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]HTTPRoute, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteList. -func (in *HTTPRouteList) DeepCopy() *HTTPRouteList { - if in == nil { - return nil - } - out := new(HTTPRouteList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *HTTPRouteList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPRouteMatch) DeepCopyInto(out *HTTPRouteMatch) { - *out = *in - if in.Path != nil { - in, out := &in.Path, &out.Path - *out = new(HTTPPathMatch) - (*in).DeepCopyInto(*out) - } - if in.Headers != nil { - in, out := &in.Headers, &out.Headers - *out = make([]HTTPHeaderMatch, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.QueryParams != nil { - in, out := &in.QueryParams, &out.QueryParams - *out = make([]HTTPQueryParamMatch, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Method != nil { - in, out := &in.Method, &out.Method - *out = new(HTTPMethod) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteMatch. -func (in *HTTPRouteMatch) DeepCopy() *HTTPRouteMatch { - if in == nil { - return nil - } - out := new(HTTPRouteMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPRouteRule) DeepCopyInto(out *HTTPRouteRule) { - *out = *in - if in.Matches != nil { - in, out := &in.Matches, &out.Matches - *out = make([]HTTPRouteMatch, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Filters != nil { - in, out := &in.Filters, &out.Filters - *out = make([]HTTPRouteFilter, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.BackendRefs != nil { - in, out := &in.BackendRefs, &out.BackendRefs - *out = make([]HTTPBackendRef, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Timeouts != nil { - in, out := &in.Timeouts, &out.Timeouts - *out = new(HTTPRouteTimeouts) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteRule. -func (in *HTTPRouteRule) DeepCopy() *HTTPRouteRule { - if in == nil { - return nil - } - out := new(HTTPRouteRule) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPRouteSpec) DeepCopyInto(out *HTTPRouteSpec) { - *out = *in - in.CommonRouteSpec.DeepCopyInto(&out.CommonRouteSpec) - if in.Hostnames != nil { - in, out := &in.Hostnames, &out.Hostnames - *out = make([]Hostname, len(*in)) - copy(*out, *in) - } - if in.Rules != nil { - in, out := &in.Rules, &out.Rules - *out = make([]HTTPRouteRule, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteSpec. -func (in *HTTPRouteSpec) DeepCopy() *HTTPRouteSpec { - if in == nil { - return nil - } - out := new(HTTPRouteSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPRouteStatus) DeepCopyInto(out *HTTPRouteStatus) { - *out = *in - in.RouteStatus.DeepCopyInto(&out.RouteStatus) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteStatus. -func (in *HTTPRouteStatus) DeepCopy() *HTTPRouteStatus { - if in == nil { - return nil - } - out := new(HTTPRouteStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPRouteTimeouts) DeepCopyInto(out *HTTPRouteTimeouts) { - *out = *in - if in.Request != nil { - in, out := &in.Request, &out.Request - *out = new(Duration) - **out = **in - } - if in.BackendRequest != nil { - in, out := &in.BackendRequest, &out.BackendRequest - *out = new(Duration) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteTimeouts. -func (in *HTTPRouteTimeouts) DeepCopy() *HTTPRouteTimeouts { - if in == nil { - return nil - } - out := new(HTTPRouteTimeouts) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPURLRewriteFilter) DeepCopyInto(out *HTTPURLRewriteFilter) { - *out = *in - if in.Hostname != nil { - in, out := &in.Hostname, &out.Hostname - *out = new(PreciseHostname) - **out = **in - } - if in.Path != nil { - in, out := &in.Path, &out.Path - *out = new(HTTPPathModifier) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPURLRewriteFilter. -func (in *HTTPURLRewriteFilter) DeepCopy() *HTTPURLRewriteFilter { - if in == nil { - return nil - } - out := new(HTTPURLRewriteFilter) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Listener) DeepCopyInto(out *Listener) { - *out = *in - if in.Hostname != nil { - in, out := &in.Hostname, &out.Hostname - *out = new(Hostname) - **out = **in - } - if in.TLS != nil { - in, out := &in.TLS, &out.TLS - *out = new(GatewayTLSConfig) - (*in).DeepCopyInto(*out) - } - if in.AllowedRoutes != nil { - in, out := &in.AllowedRoutes, &out.AllowedRoutes - *out = new(AllowedRoutes) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Listener. -func (in *Listener) DeepCopy() *Listener { - if in == nil { - return nil - } - out := new(Listener) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ListenerStatus) DeepCopyInto(out *ListenerStatus) { - *out = *in - if in.SupportedKinds != nil { - in, out := &in.SupportedKinds, &out.SupportedKinds - *out = make([]RouteGroupKind, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerStatus. -func (in *ListenerStatus) DeepCopy() *ListenerStatus { - if in == nil { - return nil - } - out := new(ListenerStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *LocalObjectReference) DeepCopyInto(out *LocalObjectReference) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalObjectReference. -func (in *LocalObjectReference) DeepCopy() *LocalObjectReference { - if in == nil { - return nil - } - out := new(LocalObjectReference) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ParametersReference) DeepCopyInto(out *ParametersReference) { - *out = *in - if in.Namespace != nil { - in, out := &in.Namespace, &out.Namespace - *out = new(Namespace) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParametersReference. -func (in *ParametersReference) DeepCopy() *ParametersReference { - if in == nil { - return nil - } - out := new(ParametersReference) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ParentReference) DeepCopyInto(out *ParentReference) { - *out = *in - if in.Group != nil { - in, out := &in.Group, &out.Group - *out = new(Group) - **out = **in - } - if in.Kind != nil { - in, out := &in.Kind, &out.Kind - *out = new(Kind) - **out = **in - } - if in.Namespace != nil { - in, out := &in.Namespace, &out.Namespace - *out = new(Namespace) - **out = **in - } - if in.SectionName != nil { - in, out := &in.SectionName, &out.SectionName - *out = new(SectionName) - **out = **in - } - if in.Port != nil { - in, out := &in.Port, &out.Port - *out = new(PortNumber) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParentReference. -func (in *ParentReference) DeepCopy() *ParentReference { - if in == nil { - return nil - } - out := new(ParentReference) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReferenceGrant) DeepCopyInto(out *ReferenceGrant) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrant. -func (in *ReferenceGrant) DeepCopy() *ReferenceGrant { - if in == nil { - return nil - } - out := new(ReferenceGrant) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ReferenceGrant) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReferenceGrantFrom) DeepCopyInto(out *ReferenceGrantFrom) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrantFrom. -func (in *ReferenceGrantFrom) DeepCopy() *ReferenceGrantFrom { - if in == nil { - return nil - } - out := new(ReferenceGrantFrom) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReferenceGrantList) DeepCopyInto(out *ReferenceGrantList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]ReferenceGrant, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrantList. -func (in *ReferenceGrantList) DeepCopy() *ReferenceGrantList { - if in == nil { - return nil - } - out := new(ReferenceGrantList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ReferenceGrantList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReferenceGrantSpec) DeepCopyInto(out *ReferenceGrantSpec) { - *out = *in - if in.From != nil { - in, out := &in.From, &out.From - *out = make([]ReferenceGrantFrom, len(*in)) - copy(*out, *in) - } - if in.To != nil { - in, out := &in.To, &out.To - *out = make([]ReferenceGrantTo, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrantSpec. -func (in *ReferenceGrantSpec) DeepCopy() *ReferenceGrantSpec { - if in == nil { - return nil - } - out := new(ReferenceGrantSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReferenceGrantTo) DeepCopyInto(out *ReferenceGrantTo) { - *out = *in - if in.Name != nil { - in, out := &in.Name, &out.Name - *out = new(ObjectName) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrantTo. -func (in *ReferenceGrantTo) DeepCopy() *ReferenceGrantTo { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrantTo. +func (in *ReferenceGrantTo) DeepCopy() *ReferenceGrantTo { if in == nil { return nil } @@ -1214,123 +321,3 @@ func (in *ReferenceGrantTo) DeepCopy() *ReferenceGrantTo { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RouteGroupKind) DeepCopyInto(out *RouteGroupKind) { - *out = *in - if in.Group != nil { - in, out := &in.Group, &out.Group - *out = new(Group) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteGroupKind. -func (in *RouteGroupKind) DeepCopy() *RouteGroupKind { - if in == nil { - return nil - } - out := new(RouteGroupKind) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RouteNamespaces) DeepCopyInto(out *RouteNamespaces) { - *out = *in - if in.From != nil { - in, out := &in.From, &out.From - *out = new(FromNamespaces) - **out = **in - } - if in.Selector != nil { - in, out := &in.Selector, &out.Selector - *out = new(v1.LabelSelector) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteNamespaces. -func (in *RouteNamespaces) DeepCopy() *RouteNamespaces { - if in == nil { - return nil - } - out := new(RouteNamespaces) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RouteParentStatus) DeepCopyInto(out *RouteParentStatus) { - *out = *in - in.ParentRef.DeepCopyInto(&out.ParentRef) - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteParentStatus. -func (in *RouteParentStatus) DeepCopy() *RouteParentStatus { - if in == nil { - return nil - } - out := new(RouteParentStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RouteStatus) DeepCopyInto(out *RouteStatus) { - *out = *in - if in.Parents != nil { - in, out := &in.Parents, &out.Parents - *out = make([]RouteParentStatus, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteStatus. -func (in *RouteStatus) DeepCopy() *RouteStatus { - if in == nil { - return nil - } - out := new(RouteStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecretObjectReference) DeepCopyInto(out *SecretObjectReference) { - *out = *in - if in.Group != nil { - in, out := &in.Group, &out.Group - *out = new(Group) - **out = **in - } - if in.Kind != nil { - in, out := &in.Kind, &out.Kind - *out = new(Kind) - **out = **in - } - if in.Namespace != nil { - in, out := &in.Namespace, &out.Namespace - *out = new(Namespace) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretObjectReference. -func (in *SecretObjectReference) DeepCopy() *SecretObjectReference { - if in == nil { - return nil - } - out := new(SecretObjectReference) - in.DeepCopyInto(out) - return out -} diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index e666d19af4..e58f040570 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null labels: diff --git a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml index eec5a8cdca..18f2ef5628 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: gatewayclasses.gateway.networking.k8s.io @@ -34,10 +34,7 @@ spec: name: Description priority: 1 type: string - deprecated: true - deprecationWarning: The v1alpha2 version of GatewayClass has been deprecated and - will be removed in a future release of the API. Please upgrade to v1beta1. - name: v1alpha2 + name: v1 schema: openAPIV3Schema: description: "GatewayClass describes a class of Gateways available to the @@ -253,7 +250,7 @@ spec: required: - spec type: object - served: false + served: true storage: false subresources: status: {} diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 28930d64a6..5f34151aa5 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: gateways.gateway.networking.k8s.io @@ -33,10 +33,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - deprecated: true - deprecationWarning: The v1alpha2 version of Gateway has been deprecated and will - be removed in a future release of the API. Please upgrade to v1beta1. - name: v1alpha2 + name: v1 schema: openAPIV3Schema: description: Gateway represents an instance of a service-traffic handling @@ -907,7 +904,7 @@ spec: required: - spec type: object - served: false + served: true storage: false subresources: status: {} diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index be30bdd1f6..f05bc525e7 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: grpcroutes.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 15e07d596c..ba7c42eba2 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: httproutes.gateway.networking.k8s.io @@ -25,10 +25,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - deprecated: true - deprecationWarning: The v1alpha2 version of HTTPRoute has been deprecated and - will be removed in a future release of the API. Please upgrade to v1beta1. - name: v1alpha2 + name: v1 schema: openAPIV3Schema: description: HTTPRoute provides a way to route HTTP requests. This includes @@ -2483,7 +2480,7 @@ spec: required: - spec type: object - served: false + served: true storage: false subresources: status: {} diff --git a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml index b771104f71..5df2ca48ec 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: referencegrants.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index 68bd6f6c77..aa6b491dd5 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: tcproutes.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index 6945362a24..154c0a6fd1 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: tlsroutes.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index b9c292825d..26a472dd5c 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: udproutes.gateway.networking.k8s.io diff --git a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml index 9b514ba4bf..fa8921cba1 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: standard creationTimestamp: null name: gatewayclasses.gateway.networking.k8s.io @@ -34,10 +34,7 @@ spec: name: Description priority: 1 type: string - deprecated: true - deprecationWarning: The v1alpha2 version of GatewayClass has been deprecated and - will be removed in a future release of the API. Please upgrade to v1beta1. - name: v1alpha2 + name: v1 schema: openAPIV3Schema: description: "GatewayClass describes a class of Gateways available to the @@ -224,7 +221,7 @@ spec: required: - spec type: object - served: false + served: true storage: false subresources: status: {} diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index 1ca74ff291..7b60011041 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: standard creationTimestamp: null name: gateways.gateway.networking.k8s.io @@ -33,10 +33,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - deprecated: true - deprecationWarning: The v1alpha2 version of Gateway has been deprecated and will - be removed in a future release of the API. Please upgrade to v1beta1. - name: v1alpha2 + name: v1 schema: openAPIV3Schema: description: Gateway represents an instance of a service-traffic handling @@ -864,7 +861,7 @@ spec: required: - spec type: object - served: false + served: true storage: false subresources: status: {} diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index ff40744d2c..9cbb0f9d94 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: standard creationTimestamp: null name: httproutes.gateway.networking.k8s.io @@ -25,10 +25,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - deprecated: true - deprecationWarning: The v1alpha2 version of HTTPRoute has been deprecated and - will be removed in a future release of the API. Please upgrade to v1beta1. - name: v1alpha2 + name: v1 schema: openAPIV3Schema: description: HTTPRoute provides a way to route HTTP requests. This includes @@ -2350,7 +2347,7 @@ spec: required: - spec type: object - served: false + served: true storage: false subresources: status: {} diff --git a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml index 76a252d69f..95953c2fe4 100644 --- a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml @@ -2,8 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 - gateway.networking.k8s.io/bundle-version: v0.8.0 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0-rc1 gateway.networking.k8s.io/channel: standard creationTimestamp: null name: referencegrants.gateway.networking.k8s.io diff --git a/conformance/tests/gateway-invalid-route-kind.go b/conformance/tests/gateway-invalid-route-kind.go index 8d2fe26926..59f1c95a2a 100644 --- a/conformance/tests/gateway-invalid-route-kind.go +++ b/conformance/tests/gateway-invalid-route-kind.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -41,13 +41,13 @@ var GatewayInvalidRouteKind = suite.ConformanceTest{ Test: func(t *testing.T, s *suite.ConformanceTestSuite) { t.Run("Gateway listener should have a false ResolvedRefs condition with reason InvalidRouteKinds and no supportedKinds", func(t *testing.T) { gwNN := types.NamespacedName{Name: "gateway-only-invalid-route-kind", Namespace: "gateway-conformance-infra"} - listeners := []v1beta1.ListenerStatus{{ - Name: v1beta1.SectionName("http"), - SupportedKinds: []v1beta1.RouteGroupKind{}, + listeners := []v1.ListenerStatus{{ + Name: v1.SectionName("http"), + SupportedKinds: []v1.RouteGroupKind{}, Conditions: []metav1.Condition{{ - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, - Reason: string(v1beta1.ListenerReasonInvalidRouteKinds), + Reason: string(v1.ListenerReasonInvalidRouteKinds), }}, AttachedRoutes: 0, }} @@ -57,16 +57,16 @@ var GatewayInvalidRouteKind = suite.ConformanceTest{ t.Run("Gateway listener should have a false ResolvedRefs condition with reason InvalidRouteKinds and HTTPRoute must be put in the supportedKinds", func(t *testing.T) { gwNN := types.NamespacedName{Name: "gateway-supported-and-invalid-route-kind", Namespace: "gateway-conformance-infra"} - listeners := []v1beta1.ListenerStatus{{ - Name: v1beta1.SectionName("http"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + listeners := []v1.ListenerStatus{{ + Name: v1.SectionName("http"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{{ - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, - Reason: string(v1beta1.ListenerReasonInvalidRouteKinds), + Reason: string(v1.ListenerReasonInvalidRouteKinds), }}, AttachedRoutes: 0, }} diff --git a/conformance/tests/gateway-invalid-route-kind.yaml b/conformance/tests/gateway-invalid-route-kind.yaml index 7318d962d6..173b8a9141 100644 --- a/conformance/tests/gateway-invalid-route-kind.yaml +++ b/conformance/tests/gateway-invalid-route-kind.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-only-invalid-route-kind @@ -15,7 +15,7 @@ spec: kinds: - kind: InvalidRoute --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-supported-and-invalid-route-kind diff --git a/conformance/tests/gateway-invalid-tls-certificateref.go b/conformance/tests/gateway-invalid-tls-certificateref.go index 8119e3a673..7711b64037 100644 --- a/conformance/tests/gateway-invalid-tls-certificateref.go +++ b/conformance/tests/gateway-invalid-tls-certificateref.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -39,16 +39,16 @@ var GatewayInvalidTLSConfiguration = suite.ConformanceTest{ }, Manifests: []string{"tests/gateway-invalid-tls-certificateref.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { - listeners := []v1beta1.ListenerStatus{{ - Name: v1beta1.SectionName("https"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + listeners := []v1.ListenerStatus{{ + Name: v1.SectionName("https"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{{ - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, - Reason: string(v1beta1.ListenerReasonInvalidCertificateRef), + Reason: string(v1.ListenerReasonInvalidCertificateRef), }}, AttachedRoutes: 0, }} diff --git a/conformance/tests/gateway-invalid-tls-certificateref.yaml b/conformance/tests/gateway-invalid-tls-certificateref.yaml index 7a1a0ac6d9..4cfae4978b 100644 --- a/conformance/tests/gateway-invalid-tls-certificateref.yaml +++ b/conformance/tests/gateway-invalid-tls-certificateref.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-certificate-nonexistent-secret @@ -18,7 +18,7 @@ spec: kind: Secret name: nonexistent-certificate --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-certificate-unsupported-group @@ -38,7 +38,7 @@ spec: kind: Secret name: tls-validity-checks-certificate --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-certificate-unsupported-kind @@ -58,7 +58,7 @@ spec: kind: WrongKind name: tls-validity-checks-certificate --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-certificate-malformed-secret @@ -85,7 +85,7 @@ metadata: namespace: gateway-conformance-infra data: # this certificate is invalid because contains an invalid pem (base64 of "Hello world"), - # and the certificate and the key are identical + # and the certificate and the key are identical tls.crt: SGVsbG8gd29ybGQK tls.key: SGVsbG8gd29ybGQK type: kubernetes.io/tls diff --git a/conformance/tests/gateway-modify-listeners.go b/conformance/tests/gateway-modify-listeners.go index 777c77986b..d1b6f23975 100644 --- a/conformance/tests/gateway-modify-listeners.go +++ b/conformance/tests/gateway-modify-listeners.go @@ -26,7 +26,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -54,23 +54,23 @@ var GatewayModifyListeners = suite.ConformanceTest{ // verify that the implementation is tracking the most recent resource changes kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) - original := &v1beta1.Gateway{} + original := &v1.Gateway{} err := s.Client.Get(ctx, gwNN, original) require.NoErrorf(t, err, "error getting Gateway: %v", err) - all := v1beta1.NamespacesFromAll + all := v1.NamespacesFromAll mutate := original.DeepCopy() // add a new listener to the Gateway spec - hostname := v1beta1.Hostname("data.test.com") - mutate.Spec.Listeners = append(mutate.Spec.Listeners, v1beta1.Listener{ + hostname := v1.Hostname("data.test.com") + mutate.Spec.Listeners = append(mutate.Spec.Listeners, v1.Listener{ Name: "http", Port: 80, - Protocol: v1beta1.HTTPProtocolType, + Protocol: v1.HTTPProtocolType, Hostname: &hostname, - AllowedRoutes: &v1beta1.AllowedRoutes{ - Namespaces: &v1beta1.RouteNamespaces{From: &all}, + AllowedRoutes: &v1.AllowedRoutes{ + Namespaces: &v1.RouteNamespaces{From: &all}, }, }) @@ -80,21 +80,21 @@ var GatewayModifyListeners = suite.ConformanceTest{ // Ensure the generation and observedGeneration sync up kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, namespaces) - listeners := []v1beta1.ListenerStatus{ + listeners := []v1.ListenerStatus{ { - Name: v1beta1.SectionName("https"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + Name: v1.SectionName("https"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{ { - Type: string(v1beta1.ListenerConditionAccepted), + Type: string(v1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", // any reason }, { - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionTrue, Reason: "", // any reason }, @@ -102,19 +102,19 @@ var GatewayModifyListeners = suite.ConformanceTest{ AttachedRoutes: 1, }, { - Name: v1beta1.SectionName("http"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + Name: v1.SectionName("http"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{ { - Type: string(v1beta1.ListenerConditionAccepted), + Type: string(v1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", // any reason }, { - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionTrue, Reason: "", // any reason }, @@ -128,7 +128,7 @@ var GatewayModifyListeners = suite.ConformanceTest{ // verify that the implementation continues to keep up to date with the resource changes we've been making kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) - updated := &v1beta1.Gateway{} + updated := &v1.Gateway{} err = s.Client.Get(ctx, gwNN, updated) require.NoErrorf(t, err, "error getting Gateway: %v", err) @@ -146,7 +146,7 @@ var GatewayModifyListeners = suite.ConformanceTest{ // verify that the implementation is tracking the most recent resource changes kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) - original := &v1beta1.Gateway{} + original := &v1.Gateway{} err := s.Client.Get(ctx, gwNN, original) require.NoErrorf(t, err, "error getting Gateway: %v", err) @@ -154,7 +154,7 @@ var GatewayModifyListeners = suite.ConformanceTest{ require.Equalf(t, 2, len(mutate.Spec.Listeners), "the gateway must have 2 listeners") // remove the "https" Gateway listener, leaving only the "http" listener - var newListeners []v1beta1.Listener + var newListeners []v1.Listener for _, listener := range mutate.Spec.Listeners { if listener.Name == "http" { newListeners = append(newListeners, listener) @@ -168,21 +168,21 @@ var GatewayModifyListeners = suite.ConformanceTest{ // Ensure the generation and observedGeneration sync up kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, namespaces) - listeners := []v1beta1.ListenerStatus{ + listeners := []v1.ListenerStatus{ { - Name: v1beta1.SectionName("http"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + Name: v1.SectionName("http"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{ { - Type: string(v1beta1.ListenerConditionAccepted), + Type: string(v1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", // any reason }, { - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionTrue, Reason: "", // any reason }, @@ -196,7 +196,7 @@ var GatewayModifyListeners = suite.ConformanceTest{ // verify that the implementation continues to keep up to date with the resource changes we've been making kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) - updated := &v1beta1.Gateway{} + updated := &v1.Gateway{} err = s.Client.Get(ctx, gwNN, updated) require.NoErrorf(t, err, "error getting Gateway: %v", err) diff --git a/conformance/tests/gateway-modify-listeners.yaml b/conformance/tests/gateway-modify-listeners.yaml index aaa53c6d08..8a7d6d9b5a 100644 --- a/conformance/tests/gateway-modify-listeners.yaml +++ b/conformance/tests/gateway-modify-listeners.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-add-listener @@ -20,7 +20,7 @@ spec: name: tls-validity-checks-certificate namespace: gateway-conformance-infra --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-route-1 @@ -35,7 +35,7 @@ spec: - name: infra-backend-v1 port: 8080 --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-remove-listener @@ -63,7 +63,7 @@ spec: namespaces: from: All --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-route-2 diff --git a/conformance/tests/gateway-observed-generation-bump.go b/conformance/tests/gateway-observed-generation-bump.go index 9f63772ba0..908c127911 100644 --- a/conformance/tests/gateway-observed-generation-bump.go +++ b/conformance/tests/gateway-observed-generation-bump.go @@ -25,7 +25,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -55,21 +55,21 @@ var GatewayObservedGenerationBump = suite.ConformanceTest{ // Sanity check kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) - original := &v1beta1.Gateway{} + original := &v1.Gateway{} err := s.Client.Get(ctx, gwNN, original) require.NoErrorf(t, err, "error getting Gateway: %v", err) - all := v1beta1.NamespacesFromAll + all := v1.NamespacesFromAll mutate := original.DeepCopy() // mutate the Gateway Spec - mutate.Spec.Listeners = append(mutate.Spec.Listeners, v1beta1.Listener{ + mutate.Spec.Listeners = append(mutate.Spec.Listeners, v1.Listener{ Name: "alternate", Port: 8080, - Protocol: v1beta1.HTTPProtocolType, - AllowedRoutes: &v1beta1.AllowedRoutes{ - Namespaces: &v1beta1.RouteNamespaces{From: &all}, + Protocol: v1.HTTPProtocolType, + AllowedRoutes: &v1.AllowedRoutes{ + Namespaces: &v1.RouteNamespaces{From: &all}, }, }) @@ -82,7 +82,7 @@ var GatewayObservedGenerationBump = suite.ConformanceTest{ // Sanity check kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) - updated := &v1beta1.Gateway{} + updated := &v1.Gateway{} err = s.Client.Get(ctx, gwNN, updated) require.NoErrorf(t, err, "error getting Gateway: %v", err) diff --git a/conformance/tests/gateway-observed-generation-bump.yaml b/conformance/tests/gateway-observed-generation-bump.yaml index 31fe593d9f..98c93032ba 100644 --- a/conformance/tests/gateway-observed-generation-bump.yaml +++ b/conformance/tests/gateway-observed-generation-bump.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-observed-generation-bump diff --git a/conformance/tests/gateway-secret-invalid-reference-grant.go b/conformance/tests/gateway-secret-invalid-reference-grant.go index 87c10f3af3..69dd4873af 100644 --- a/conformance/tests/gateway-secret-invalid-reference-grant.go +++ b/conformance/tests/gateway-secret-invalid-reference-grant.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -43,16 +43,16 @@ var GatewaySecretInvalidReferenceGrant = suite.ConformanceTest{ gwNN := types.NamespacedName{Name: "gateway-secret-invalid-reference-grant", Namespace: "gateway-conformance-infra"} t.Run("Gateway listener should have a false ResolvedRefs condition with reason RefNotPermitted", func(t *testing.T) { - listeners := []v1beta1.ListenerStatus{{ - Name: v1beta1.SectionName("https"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + listeners := []v1.ListenerStatus{{ + Name: v1.SectionName("https"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{{ - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, - Reason: string(v1beta1.ListenerReasonRefNotPermitted), + Reason: string(v1.ListenerReasonRefNotPermitted), }}, AttachedRoutes: 0, }} diff --git a/conformance/tests/gateway-secret-invalid-reference-grant.yaml b/conformance/tests/gateway-secret-invalid-reference-grant.yaml index ff201fd2de..1918d3221d 100644 --- a/conformance/tests/gateway-secret-invalid-reference-grant.yaml +++ b/conformance/tests/gateway-secret-invalid-reference-grant.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-secret-invalid-reference-grant @@ -19,7 +19,7 @@ spec: name: certificate namespace: gateway-conformance-web-backend --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: ReferenceGrant metadata: name: reference-grant-wrong-namespace @@ -34,7 +34,7 @@ spec: kind: Secret name: certificate --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: ReferenceGrant metadata: name: reference-grant-wrong-from-group @@ -49,7 +49,7 @@ spec: kind: Secret name: certificate --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: ReferenceGrant metadata: name: reference-grant-wrong-from-kind @@ -64,7 +64,7 @@ spec: kind: Secret name: certificate --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: ReferenceGrant metadata: name: reference-grant-wrong-from-namespace @@ -79,7 +79,7 @@ spec: kind: Secret name: certificate --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: ReferenceGrant metadata: name: reference-grant-wrong-to-group @@ -94,7 +94,7 @@ spec: kind: Secret name: not-the-certificate-youre-looking-for --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: ReferenceGrant metadata: name: reference-grant-wrong-to-kind @@ -109,7 +109,7 @@ spec: kind: Service name: certificate --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: ReferenceGrant metadata: name: reference-grant-wrong-to-name diff --git a/conformance/tests/gateway-secret-missing-reference-grant.go b/conformance/tests/gateway-secret-missing-reference-grant.go index 2b4e747bb2..67719d70da 100644 --- a/conformance/tests/gateway-secret-missing-reference-grant.go +++ b/conformance/tests/gateway-secret-missing-reference-grant.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -43,16 +43,16 @@ var GatewaySecretMissingReferenceGrant = suite.ConformanceTest{ gwNN := types.NamespacedName{Name: "gateway-secret-missing-reference-grant", Namespace: "gateway-conformance-infra"} t.Run("Gateway listener should have a false ResolvedRefs condition with reason RefNotPermitted", func(t *testing.T) { - listeners := []v1beta1.ListenerStatus{{ - Name: v1beta1.SectionName("https"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + listeners := []v1.ListenerStatus{{ + Name: v1.SectionName("https"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{{ - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, - Reason: string(v1beta1.ListenerReasonRefNotPermitted), + Reason: string(v1.ListenerReasonRefNotPermitted), }}, AttachedRoutes: 0, }} diff --git a/conformance/tests/gateway-secret-missing-reference-grant.yaml b/conformance/tests/gateway-secret-missing-reference-grant.yaml index a3c53abe1a..5af7ee1fb4 100644 --- a/conformance/tests/gateway-secret-missing-reference-grant.yaml +++ b/conformance/tests/gateway-secret-missing-reference-grant.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-secret-missing-reference-grant diff --git a/conformance/tests/gateway-secret-reference-grant-all-in-namespace.go b/conformance/tests/gateway-secret-reference-grant-all-in-namespace.go index f9ed96e610..101ac49551 100644 --- a/conformance/tests/gateway-secret-reference-grant-all-in-namespace.go +++ b/conformance/tests/gateway-secret-reference-grant-all-in-namespace.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -43,20 +43,20 @@ var GatewaySecretReferenceGrantAllInNamespace = suite.ConformanceTest{ gwNN := types.NamespacedName{Name: "gateway-secret-reference-grant-all-in-namespace", Namespace: "gateway-conformance-infra"} t.Run("Gateway listener should have a true ResolvedRefs condition and a true Programmed condition", func(t *testing.T) { - listeners := []v1beta1.ListenerStatus{{ - Name: v1beta1.SectionName("https"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + listeners := []v1.ListenerStatus{{ + Name: v1.SectionName("https"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{ { - Type: string(v1beta1.ListenerConditionProgrammed), + Type: string(v1.ListenerConditionProgrammed), Status: metav1.ConditionTrue, - Reason: string(v1beta1.ListenerReasonProgrammed), + Reason: string(v1.ListenerReasonProgrammed), }, { - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionTrue, Reason: "", // any reason }, diff --git a/conformance/tests/gateway-secret-reference-grant-all-in-namespace.yaml b/conformance/tests/gateway-secret-reference-grant-all-in-namespace.yaml index 034c9f7f5b..620ff3ef95 100644 --- a/conformance/tests/gateway-secret-reference-grant-all-in-namespace.yaml +++ b/conformance/tests/gateway-secret-reference-grant-all-in-namespace.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-secret-reference-grant-all-in-namespace diff --git a/conformance/tests/gateway-secret-reference-grant-specific.go b/conformance/tests/gateway-secret-reference-grant-specific.go index ae883d3092..cf0ca7f407 100644 --- a/conformance/tests/gateway-secret-reference-grant-specific.go +++ b/conformance/tests/gateway-secret-reference-grant-specific.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -43,20 +43,20 @@ var GatewaySecretReferenceGrantSpecific = suite.ConformanceTest{ gwNN := types.NamespacedName{Name: "gateway-secret-reference-grant-specific", Namespace: "gateway-conformance-infra"} t.Run("Gateway listener should have a true ResolvedRefs condition and a true Programmed condition", func(t *testing.T) { - listeners := []v1beta1.ListenerStatus{{ - Name: v1beta1.SectionName("https"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + listeners := []v1.ListenerStatus{{ + Name: v1.SectionName("https"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{ { - Type: string(v1beta1.ListenerConditionProgrammed), + Type: string(v1.ListenerConditionProgrammed), Status: metav1.ConditionTrue, - Reason: string(v1beta1.ListenerReasonProgrammed), + Reason: string(v1.ListenerReasonProgrammed), }, { - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionTrue, Reason: "", // any reason }, diff --git a/conformance/tests/gateway-secret-reference-grant-specific.yaml b/conformance/tests/gateway-secret-reference-grant-specific.yaml index 0f15710900..8de26a551e 100644 --- a/conformance/tests/gateway-secret-reference-grant-specific.yaml +++ b/conformance/tests/gateway-secret-reference-grant-specific.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-secret-reference-grant-specific diff --git a/conformance/tests/gateway-static-addresses.go b/conformance/tests/gateway-static-addresses.go index 05e7b40d5d..817462ce41 100644 --- a/conformance/tests/gateway-static-addresses.go +++ b/conformance/tests/gateway-static-addresses.go @@ -26,7 +26,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -76,7 +76,7 @@ var GatewayStaticAddresses = suite.ConformanceTest{ kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) t.Logf("retrieving Gateway %s/%s and noting the provided addresses", gwNN.Namespace, gwNN.Name) - currentGW := &v1beta1.Gateway{} + currentGW := &v1.Gateway{} err := s.Client.Get(ctx, gwNN, currentGW) require.NoError(t, err, "error getting Gateway: %v", err) require.Len(t, currentGW.Spec.Addresses, 3, "expected 3 addresses on the Gateway, one invalid, one usable and one unusable. somehow got %d", len(currentGW.Spec.Addresses)) @@ -86,9 +86,9 @@ var GatewayStaticAddresses = suite.ConformanceTest{ t.Logf("verifying that the Gateway %s/%s is NOT accepted due to an address type that the implementation doesn't support", gwNN.Namespace, gwNN.Name) kubernetes.GatewayMustHaveCondition(t, s.Client, s.TimeoutConfig, gwNN, metav1.Condition{ - Type: string(v1beta1.GatewayConditionAccepted), + Type: string(v1.GatewayConditionAccepted), Status: metav1.ConditionFalse, - Reason: string(v1beta1.GatewayReasonUnsupportedAddress), + Reason: string(v1.GatewayReasonUnsupportedAddress), }) t.Logf("patching Gateway %s/%s to remove the invalid address %s", gwNN.Namespace, gwNN.Name, invalidAddress.Value) @@ -102,14 +102,14 @@ var GatewayStaticAddresses = suite.ConformanceTest{ err = s.Client.Get(ctx, gwNN, currentGW) require.NoError(t, err, "error getting Gateway: %v", err) kubernetes.GatewayMustHaveCondition(t, s.Client, s.TimeoutConfig, gwNN, metav1.Condition{ - Type: string(v1beta1.GatewayConditionAccepted), + Type: string(v1.GatewayConditionAccepted), Status: metav1.ConditionTrue, - Reason: string(v1beta1.GatewayReasonAccepted), + Reason: string(v1.GatewayReasonAccepted), }) kubernetes.GatewayMustHaveCondition(t, s.Client, s.TimeoutConfig, gwNN, metav1.Condition{ - Type: string(v1beta1.GatewayConditionProgrammed), + Type: string(v1.GatewayConditionProgrammed), Status: metav1.ConditionFalse, - Reason: string(v1beta1.GatewayReasonAddressNotUsable), + Reason: string(v1.GatewayReasonAddressNotUsable), }) t.Logf("patching Gateway %s/%s to remove the unusable address %s", gwNN.Namespace, gwNN.Name, unusableAddress.Value) @@ -123,14 +123,14 @@ var GatewayStaticAddresses = suite.ConformanceTest{ err = s.Client.Get(ctx, gwNN, currentGW) require.NoError(t, err, "error getting Gateway: %v", err) kubernetes.GatewayMustHaveCondition(t, s.Client, s.TimeoutConfig, gwNN, metav1.Condition{ - Type: string(v1beta1.GatewayConditionAccepted), + Type: string(v1.GatewayConditionAccepted), Status: metav1.ConditionTrue, - Reason: string(v1beta1.GatewayReasonAccepted), + Reason: string(v1.GatewayReasonAccepted), }) kubernetes.GatewayMustHaveCondition(t, s.Client, s.TimeoutConfig, gwNN, metav1.Condition{ - Type: string(v1beta1.GatewayConditionProgrammed), + Type: string(v1.GatewayConditionProgrammed), Status: metav1.ConditionTrue, - Reason: string(v1beta1.GatewayReasonProgrammed), + Reason: string(v1.GatewayReasonProgrammed), }) kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, finalExpectedListenerState) require.Len(t, currentGW.Spec.Addresses, 1, "expected only 1 address left specified on Gateway") @@ -144,7 +144,7 @@ var GatewayStaticAddresses = suite.ConformanceTest{ // Private Helper Functions // ----------------------------------------------------------------------------- -func filterAddr(addrs []v1beta1.GatewayAddress, filter v1beta1.GatewayAddress) (newAddrs []v1beta1.GatewayAddress) { +func filterAddr(addrs []v1.GatewayAddress, filter v1.GatewayAddress) (newAddrs []v1.GatewayAddress) { for _, addr := range addrs { if addr.Value != filter.Value { newAddrs = append(newAddrs, addr) @@ -153,21 +153,21 @@ func filterAddr(addrs []v1beta1.GatewayAddress, filter v1beta1.GatewayAddress) ( return } -var finalExpectedListenerState = []v1beta1.ListenerStatus{ +var finalExpectedListenerState = []v1.ListenerStatus{ { - Name: v1beta1.SectionName("http"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + Name: v1.SectionName("http"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{ { - Type: string(v1beta1.ListenerConditionAccepted), + Type: string(v1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", // any reason }, { - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionTrue, Reason: "", // any reason }, diff --git a/conformance/tests/gateway-static-addresses.yaml b/conformance/tests/gateway-static-addresses.yaml index 2ecbdc26d7..d0a9f5f150 100644 --- a/conformance/tests/gateway-static-addresses.yaml +++ b/conformance/tests/gateway-static-addresses.yaml @@ -1,5 +1,5 @@ --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-static-addresses diff --git a/conformance/tests/gateway-with-attached-routes-with-port-8080.yaml b/conformance/tests/gateway-with-attached-routes-with-port-8080.yaml index a6fc8bad80..2458901a84 100644 --- a/conformance/tests/gateway-with-attached-routes-with-port-8080.yaml +++ b/conformance/tests/gateway-with-attached-routes-with-port-8080.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-with-two-listeners-and-one-attached-route @@ -23,7 +23,7 @@ spec: namespaces: from: All --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-route-4 diff --git a/conformance/tests/gateway-with-attached-routes.go b/conformance/tests/gateway-with-attached-routes.go index 53b5659c23..b49fcd2f66 100644 --- a/conformance/tests/gateway-with-attached-routes.go +++ b/conformance/tests/gateway-with-attached-routes.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -41,20 +41,20 @@ var GatewayWithAttachedRoutes = suite.ConformanceTest{ Test: func(t *testing.T, s *suite.ConformanceTestSuite) { t.Run("Gateway listener should have one valid http routes attached", func(t *testing.T) { gwNN := types.NamespacedName{Name: "gateway-with-one-attached-route", Namespace: "gateway-conformance-infra"} - listeners := []v1beta1.ListenerStatus{{ - Name: v1beta1.SectionName("http"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + listeners := []v1.ListenerStatus{{ + Name: v1.SectionName("http"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{ { - Type: string(v1beta1.ListenerConditionAccepted), + Type: string(v1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", // any reason }, { - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionTrue, Reason: "", // any reason }, @@ -67,20 +67,20 @@ var GatewayWithAttachedRoutes = suite.ConformanceTest{ t.Run("Gateway listener should have two valid http routes attached", func(t *testing.T) { gwNN := types.NamespacedName{Name: "gateway-with-two-attached-routes", Namespace: "gateway-conformance-infra"} - listeners := []v1beta1.ListenerStatus{{ - Name: v1beta1.SectionName("http"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + listeners := []v1.ListenerStatus{{ + Name: v1.SectionName("http"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{ { - Type: string(v1beta1.ListenerConditionAccepted), + Type: string(v1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", // any reason }, { - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionTrue, Reason: "", // any reason }, @@ -104,21 +104,21 @@ var GatewayWithAttachedRoutesWithPort8080 = suite.ConformanceTest{ Test: func(t *testing.T, s *suite.ConformanceTestSuite) { t.Run("Gateway listener should have attached route by specifying the sectionName", func(t *testing.T) { gwNN := types.NamespacedName{Name: "gateway-with-two-listeners-and-one-attached-route", Namespace: "gateway-conformance-infra"} - listeners := []v1beta1.ListenerStatus{ + listeners := []v1.ListenerStatus{ { - Name: v1beta1.SectionName("http-unattached"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + Name: v1.SectionName("http-unattached"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{ { - Type: string(v1beta1.ListenerConditionAccepted), + Type: string(v1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", // any reason }, { - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionTrue, Reason: "", // any reason }, @@ -126,19 +126,19 @@ var GatewayWithAttachedRoutesWithPort8080 = suite.ConformanceTest{ AttachedRoutes: 0, }, { - Name: v1beta1.SectionName("http"), - SupportedKinds: []v1beta1.RouteGroupKind{{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), - Kind: v1beta1.Kind("HTTPRoute"), + Name: v1.SectionName("http"), + SupportedKinds: []v1.RouteGroupKind{{ + Group: (*v1.Group)(&v1.GroupVersion.Group), + Kind: v1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{ { - Type: string(v1beta1.ListenerConditionAccepted), + Type: string(v1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", // any reason }, { - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(v1.ListenerConditionResolvedRefs), Status: metav1.ConditionTrue, Reason: "", // any reason }, diff --git a/conformance/tests/gateway-with-attached-routes.yaml b/conformance/tests/gateway-with-attached-routes.yaml index b067f99c7b..d4f051699b 100644 --- a/conformance/tests/gateway-with-attached-routes.yaml +++ b/conformance/tests/gateway-with-attached-routes.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-with-one-attached-route @@ -20,7 +20,7 @@ spec: # to all namespaces kubernetes.io/metadata.name: gateway-conformance-infra --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-route-1 @@ -35,7 +35,7 @@ spec: - name: infra-backend-v1 port: 8080 --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-with-two-attached-routes @@ -57,7 +57,7 @@ spec: # to all namespaces kubernetes.io/metadata.name: gateway-conformance-infra --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-route-2 @@ -72,7 +72,7 @@ spec: - name: infra-backend-v1 port: 8080 --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-route-3 diff --git a/conformance/tests/gatewayclass-observed-generation-bump.go b/conformance/tests/gatewayclass-observed-generation-bump.go index b3e3c693fc..3f2b780314 100644 --- a/conformance/tests/gatewayclass-observed-generation-bump.go +++ b/conformance/tests/gatewayclass-observed-generation-bump.go @@ -25,7 +25,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -50,7 +50,7 @@ var GatewayClassObservedGenerationBump = suite.ConformanceTest{ kubernetes.GWCMustHaveAcceptedConditionAny(t, s.Client, s.TimeoutConfig, gwc.Name) - original := &v1beta1.GatewayClass{} + original := &v1.GatewayClass{} err := s.Client.Get(ctx, gwc, original) require.NoErrorf(t, err, "error getting GatewayClass: %v", err) @@ -67,7 +67,7 @@ var GatewayClassObservedGenerationBump = suite.ConformanceTest{ // Ensure the generation and observedGeneration sync up kubernetes.GWCMustHaveAcceptedConditionAny(t, s.Client, s.TimeoutConfig, gwc.Name) - updated := &v1beta1.GatewayClass{} + updated := &v1.GatewayClass{} err = s.Client.Get(ctx, gwc, updated) require.NoErrorf(t, err, "error getting GatewayClass: %v", err) diff --git a/conformance/tests/gatewayclass-observed-generation-bump.yaml b/conformance/tests/gatewayclass-observed-generation-bump.yaml index 0ad3d1fd36..2224fab373 100644 --- a/conformance/tests/gatewayclass-observed-generation-bump.yaml +++ b/conformance/tests/gatewayclass-observed-generation-bump.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: gatewayclass-observed-generation-bump diff --git a/conformance/tests/httproute-cross-namespace.yaml b/conformance/tests/httproute-cross-namespace.yaml index 97aee27f54..2c2ccdcdeb 100644 --- a/conformance/tests/httproute-cross-namespace.yaml +++ b/conformance/tests/httproute-cross-namespace.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: cross-namespace diff --git a/conformance/tests/httproute-disallowed-kind.go b/conformance/tests/httproute-disallowed-kind.go index b334f36f8f..71f2002fd7 100644 --- a/conformance/tests/httproute-disallowed-kind.go +++ b/conformance/tests/httproute-disallowed-kind.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -51,9 +51,9 @@ var HTTPRouteDisallowedKind = suite.ConformanceTest{ t.Run("Route should not have been accepted with reason NotAllowedByListeners", func(t *testing.T) { kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, metav1.Condition{ - Type: string(v1beta1.RouteConditionAccepted), + Type: string(v1.RouteConditionAccepted), Status: metav1.ConditionFalse, - Reason: string(v1beta1.RouteReasonNotAllowedByListeners), + Reason: string(v1.RouteReasonNotAllowedByListeners), }) }) t.Run("Route should not have Parents set in status", func(t *testing.T) { diff --git a/conformance/tests/httproute-disallowed-kind.yaml b/conformance/tests/httproute-disallowed-kind.yaml index ed12bb0fdc..1752e8a4f8 100644 --- a/conformance/tests/httproute-disallowed-kind.yaml +++ b/conformance/tests/httproute-disallowed-kind.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: tlsroutes-only @@ -17,7 +17,7 @@ spec: kinds: - kind: TLSRoute --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: disallowed-kind diff --git a/conformance/tests/httproute-exact-path-matching.yaml b/conformance/tests/httproute-exact-path-matching.yaml index b670cb1a64..0c7fe461ec 100644 --- a/conformance/tests/httproute-exact-path-matching.yaml +++ b/conformance/tests/httproute-exact-path-matching.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: exact-matching diff --git a/conformance/tests/httproute-header-matching.yaml b/conformance/tests/httproute-header-matching.yaml index ef74e9de84..7114000199 100644 --- a/conformance/tests/httproute-header-matching.yaml +++ b/conformance/tests/httproute-header-matching.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: header-matching diff --git a/conformance/tests/httproute-hostname-intersection.go b/conformance/tests/httproute-hostname-intersection.go index f4adc7bc49..15234a2cb6 100644 --- a/conformance/tests/httproute-hostname-intersection.go +++ b/conformance/tests/httproute-hostname-intersection.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -206,14 +206,14 @@ var HTTPRouteHostnameIntersection = suite.ConformanceTest{ gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN)) routeNN := types.NamespacedName{Namespace: ns, Name: "no-intersecting-hosts"} - parents := []v1beta1.RouteParentStatus{{ + parents := []v1.RouteParentStatus{{ ParentRef: parentRefTo(gwNN), - ControllerName: v1beta1.GatewayController(suite.ControllerName), + ControllerName: v1.GatewayController(suite.ControllerName), Conditions: []metav1.Condition{ { - Type: string(v1beta1.RouteConditionAccepted), + Type: string(v1.RouteConditionAccepted), Status: metav1.ConditionFalse, - Reason: string(v1beta1.RouteReasonNoMatchingListenerHostname), + Reason: string(v1.RouteReasonNoMatchingListenerHostname), }, }, }} @@ -244,15 +244,15 @@ var HTTPRouteHostnameIntersection = suite.ConformanceTest{ }, } -func parentRefTo(gateway types.NamespacedName) v1beta1.ParentReference { +func parentRefTo(gateway types.NamespacedName) v1.ParentReference { var ( - group = v1beta1.Group(v1beta1.GroupName) - kind = v1beta1.Kind("Gateway") - namespace = v1beta1.Namespace(gateway.Namespace) - name = v1beta1.ObjectName(gateway.Name) + group = v1.Group(v1.GroupName) + kind = v1.Kind("Gateway") + namespace = v1.Namespace(gateway.Namespace) + name = v1.ObjectName(gateway.Name) ) - return v1beta1.ParentReference{ + return v1.ParentReference{ Group: &group, Kind: &kind, Namespace: &namespace, diff --git a/conformance/tests/httproute-hostname-intersection.yaml b/conformance/tests/httproute-hostname-intersection.yaml index aa5864be0c..9173fa96e3 100644 --- a/conformance/tests/httproute-hostname-intersection.yaml +++ b/conformance/tests/httproute-hostname-intersection.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: httproute-hostname-intersection @@ -28,7 +28,7 @@ spec: from: Same hostname: "*.anotherwildcard.io" --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: specific-host-matches-listener-specific-host @@ -50,7 +50,7 @@ spec: - name: infra-backend-v1 port: 8080 --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: specific-host-matches-listener-wildcard-host @@ -74,7 +74,7 @@ spec: - name: infra-backend-v2 port: 8080 --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: wildcard-host-matches-listener-specific-host @@ -95,7 +95,7 @@ spec: - name: infra-backend-v3 port: 8080 --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: wildcard-host-matches-listener-wildcard-host @@ -115,7 +115,7 @@ spec: - name: infra-backend-v1 port: 8080 --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: no-intersecting-hosts diff --git a/conformance/tests/httproute-invalid-backendref-nonexistent.go b/conformance/tests/httproute-invalid-backendref-nonexistent.go index 318432dea3..d69c3133a1 100644 --- a/conformance/tests/httproute-invalid-backendref-nonexistent.go +++ b/conformance/tests/httproute-invalid-backendref-nonexistent.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -49,9 +49,9 @@ var HTTPRouteInvalidNonExistentBackendRef = suite.ConformanceTest{ t.Run("HTTPRoute with only a nonexistent BackendRef has a ResolvedRefs Condition with status False and Reason BackendNotFound", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ - Type: string(v1beta1.RouteConditionResolvedRefs), + Type: string(v1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, - Reason: string(v1beta1.RouteReasonBackendNotFound), + Reason: string(v1.RouteReasonBackendNotFound), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) diff --git a/conformance/tests/httproute-invalid-backendref-nonexistent.yaml b/conformance/tests/httproute-invalid-backendref-nonexistent.yaml index 2bf55aafc2..97c771a042 100644 --- a/conformance/tests/httproute-invalid-backendref-nonexistent.yaml +++ b/conformance/tests/httproute-invalid-backendref-nonexistent.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-nonexistent-backend-ref diff --git a/conformance/tests/httproute-invalid-backendref-unknown-kind.go b/conformance/tests/httproute-invalid-backendref-unknown-kind.go index 83bad184e3..93c179ef70 100644 --- a/conformance/tests/httproute-invalid-backendref-unknown-kind.go +++ b/conformance/tests/httproute-invalid-backendref-unknown-kind.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -50,9 +50,9 @@ var HTTPRouteInvalidBackendRefUnknownKind = suite.ConformanceTest{ // The Route must have a ResolvedRefs Condition with a InvalidKind Reason. t.Run("HTTPRoute with Invalid Kind has a ResolvedRefs Condition with status False and Reason InvalidKind", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ - Type: string(v1beta1.RouteConditionResolvedRefs), + Type: string(v1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, - Reason: string(v1beta1.RouteReasonInvalidKind), + Reason: string(v1.RouteReasonInvalidKind), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) diff --git a/conformance/tests/httproute-invalid-backendref-unknown-kind.yaml b/conformance/tests/httproute-invalid-backendref-unknown-kind.yaml index b01aa1224f..7c84541a2d 100644 --- a/conformance/tests/httproute-invalid-backendref-unknown-kind.yaml +++ b/conformance/tests/httproute-invalid-backendref-unknown-kind.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-backend-ref-unknown-kind diff --git a/conformance/tests/httproute-invalid-cross-namespace-backend-ref.go b/conformance/tests/httproute-invalid-cross-namespace-backend-ref.go index 8d5dcbf765..b2f313805c 100644 --- a/conformance/tests/httproute-invalid-cross-namespace-backend-ref.go +++ b/conformance/tests/httproute-invalid-cross-namespace-backend-ref.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -50,9 +50,9 @@ var HTTPRouteInvalidCrossNamespaceBackendRef = suite.ConformanceTest{ t.Run("HTTPRoute with a cross-namespace BackendRef and no ReferenceGrant has a ResolvedRefs Condition with status False and Reason RefNotPermitted", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ - Type: string(v1beta1.RouteConditionResolvedRefs), + Type: string(v1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, - Reason: string(v1beta1.RouteReasonRefNotPermitted), + Reason: string(v1.RouteReasonRefNotPermitted), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) diff --git a/conformance/tests/httproute-invalid-cross-namespace-backend-ref.yaml b/conformance/tests/httproute-invalid-cross-namespace-backend-ref.yaml index 9c81c1a4b2..b88c67b2e7 100644 --- a/conformance/tests/httproute-invalid-cross-namespace-backend-ref.yaml +++ b/conformance/tests/httproute-invalid-cross-namespace-backend-ref.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-cross-namespace-backend-ref diff --git a/conformance/tests/httproute-invalid-cross-namespace-parent-ref.go b/conformance/tests/httproute-invalid-cross-namespace-parent-ref.go index 82bf00e5c7..ac6fb7a055 100644 --- a/conformance/tests/httproute-invalid-cross-namespace-parent-ref.go +++ b/conformance/tests/httproute-invalid-cross-namespace-parent-ref.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -50,9 +50,9 @@ var HTTPRouteInvalidCrossNamespaceParentRef = suite.ConformanceTest{ // namespaces, in which case they are not obligated to populate this condition on routes they cannot access. t.Run("HTTPRoute should have an Accepted: false condition with reason NotAllowedByListeners", func(t *testing.T) { acceptedCond := metav1.Condition{ - Type: string(v1beta1.RouteConditionAccepted), + Type: string(v1.RouteConditionAccepted), Status: metav1.ConditionFalse, - Reason: string(v1beta1.RouteReasonNotAllowedByListeners), + Reason: string(v1.RouteReasonNotAllowedByListeners), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, acceptedCond) diff --git a/conformance/tests/httproute-invalid-cross-namespace-parent-ref.yaml b/conformance/tests/httproute-invalid-cross-namespace-parent-ref.yaml index aed587f2e1..e184b9345c 100644 --- a/conformance/tests/httproute-invalid-cross-namespace-parent-ref.yaml +++ b/conformance/tests/httproute-invalid-cross-namespace-parent-ref.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-cross-namespace-parent-ref diff --git a/conformance/tests/httproute-invalid-parentref-not-matching-listener-port.go b/conformance/tests/httproute-invalid-parentref-not-matching-listener-port.go index e05f77faf3..5ea6e56a86 100644 --- a/conformance/tests/httproute-invalid-parentref-not-matching-listener-port.go +++ b/conformance/tests/httproute-invalid-parentref-not-matching-listener-port.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -48,9 +48,9 @@ var HTTPRouteInvalidParentRefNotMatchingListenerPort = suite.ConformanceTest{ // The Route must have an Accepted Condition with a NoMatchingParent Reason. t.Run("HTTPRoute with no matching port in ParentRef has an Accepted Condition with status False and Reason NoMatchingParent", func(t *testing.T) { acceptedCond := metav1.Condition{ - Type: string(v1beta1.RouteConditionAccepted), + Type: string(v1.RouteConditionAccepted), Status: metav1.ConditionFalse, - Reason: string(v1beta1.RouteReasonNoMatchingParent), + Reason: string(v1.RouteReasonNoMatchingParent), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, acceptedCond) diff --git a/conformance/tests/httproute-invalid-parentref-not-matching-listener-port.yaml b/conformance/tests/httproute-invalid-parentref-not-matching-listener-port.yaml index 24cd36ea26..934492a600 100644 --- a/conformance/tests/httproute-invalid-parentref-not-matching-listener-port.yaml +++ b/conformance/tests/httproute-invalid-parentref-not-matching-listener-port.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httproute-listener-not-matching-route-port diff --git a/conformance/tests/httproute-invalid-parentref-not-matching-section-name.go b/conformance/tests/httproute-invalid-parentref-not-matching-section-name.go index 0fe909f514..e7fd758d65 100644 --- a/conformance/tests/httproute-invalid-parentref-not-matching-section-name.go +++ b/conformance/tests/httproute-invalid-parentref-not-matching-section-name.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -46,9 +46,9 @@ var HTTPRouteInvalidParentRefNotMatchingSectionName = suite.ConformanceTest{ // The Route must have an Accepted Condition with a NoMatchingParent Reason. t.Run("HTTPRoute with no matching sectionName in ParentRef has an Accepted Condition with status False and Reason NoMatchingParent", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ - Type: string(v1beta1.RouteConditionAccepted), + Type: string(v1.RouteConditionAccepted), Status: metav1.ConditionFalse, - Reason: string(v1beta1.RouteReasonNoMatchingParent), + Reason: string(v1.RouteReasonNoMatchingParent), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) diff --git a/conformance/tests/httproute-invalid-parentref-not-matching-section-name.yaml b/conformance/tests/httproute-invalid-parentref-not-matching-section-name.yaml index b449965d98..5ba57e1663 100644 --- a/conformance/tests/httproute-invalid-parentref-not-matching-section-name.yaml +++ b/conformance/tests/httproute-invalid-parentref-not-matching-section-name.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httproute-listener-not-matching-section-name diff --git a/conformance/tests/httproute-invalid-reference-grant.go b/conformance/tests/httproute-invalid-reference-grant.go index e209f0f24a..010e9d81df 100644 --- a/conformance/tests/httproute-invalid-reference-grant.go +++ b/conformance/tests/httproute-invalid-reference-grant.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -48,9 +48,9 @@ var HTTPRouteInvalidReferenceGrant = suite.ConformanceTest{ t.Run("HTTPRoute with BackendRef in another namespace and no ReferenceGrant covering the Service has a ResolvedRefs Condition with status False and Reason RefNotPermitted", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ - Type: string(v1beta1.RouteConditionResolvedRefs), + Type: string(v1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, - Reason: string(v1beta1.RouteReasonRefNotPermitted), + Reason: string(v1.RouteReasonRefNotPermitted), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) diff --git a/conformance/tests/httproute-invalid-reference-grant.yaml b/conformance/tests/httproute-invalid-reference-grant.yaml index 5aab35f2cd..08be4f7b54 100644 --- a/conformance/tests/httproute-invalid-reference-grant.yaml +++ b/conformance/tests/httproute-invalid-reference-grant.yaml @@ -104,7 +104,7 @@ spec: kind: Secret name: not-the-service-youre-looking-for --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: reference-grant diff --git a/conformance/tests/httproute-listener-hostname-matching.yaml b/conformance/tests/httproute-listener-hostname-matching.yaml index f00c9786d1..d162f1a4ae 100644 --- a/conformance/tests/httproute-listener-hostname-matching.yaml +++ b/conformance/tests/httproute-listener-hostname-matching.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: httproute-listener-hostname-matching @@ -35,7 +35,7 @@ spec: from: Same hostname: "*.foo.com" --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend-v1 @@ -50,7 +50,7 @@ spec: - name: infra-backend-v1 port: 8080 --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend-v2 @@ -65,7 +65,7 @@ spec: - name: infra-backend-v2 port: 8080 --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend-v3 diff --git a/conformance/tests/httproute-matching-across-routes.yaml b/conformance/tests/httproute-matching-across-routes.yaml index f06e30d8b8..f88f7e8b0c 100644 --- a/conformance/tests/httproute-matching-across-routes.yaml +++ b/conformance/tests/httproute-matching-across-routes.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: matching-part1 @@ -21,7 +21,7 @@ spec: - name: infra-backend-v1 port: 8080 --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: matching-part2 diff --git a/conformance/tests/httproute-matching.yaml b/conformance/tests/httproute-matching.yaml index b35171ed7e..b69a51a754 100644 --- a/conformance/tests/httproute-matching.yaml +++ b/conformance/tests/httproute-matching.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: matching diff --git a/conformance/tests/httproute-method-matching.yaml b/conformance/tests/httproute-method-matching.yaml index 5396f084ee..162ef4cc19 100644 --- a/conformance/tests/httproute-method-matching.yaml +++ b/conformance/tests/httproute-method-matching.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: method-matching diff --git a/conformance/tests/httproute-observed-generation-bump.go b/conformance/tests/httproute-observed-generation-bump.go index ade4a5927f..e5514aba13 100644 --- a/conformance/tests/httproute-observed-generation-bump.go +++ b/conformance/tests/httproute-observed-generation-bump.go @@ -26,7 +26,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -54,7 +54,7 @@ var HTTPRouteObservedGenerationBump = suite.ConformanceTest{ namespaces := []string{"gateway-conformance-infra"} kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, namespaces) - original := &v1beta1.HTTPRoute{} + original := &v1.HTTPRoute{} err := suite.Client.Get(ctx, routeNN, original) require.NoErrorf(t, err, "error getting HTTPRoute: %v", err) @@ -67,13 +67,13 @@ var HTTPRouteObservedGenerationBump = suite.ConformanceTest{ require.NoErrorf(t, err, "error patching the HTTPRoute: %v", err) kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, metav1.Condition{ - Type: string(v1beta1.RouteConditionAccepted), + Type: string(v1.RouteConditionAccepted), Status: metav1.ConditionTrue, Reason: "", // any reason }) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) - updated := &v1beta1.HTTPRoute{} + updated := &v1.HTTPRoute{} err = suite.Client.Get(ctx, routeNN, updated) require.NoErrorf(t, err, "error getting Gateway: %v", err) diff --git a/conformance/tests/httproute-observed-generation-bump.yaml b/conformance/tests/httproute-observed-generation-bump.yaml index 8de5c76455..1a82dafd09 100644 --- a/conformance/tests/httproute-observed-generation-bump.yaml +++ b/conformance/tests/httproute-observed-generation-bump.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: observed-generation-bump diff --git a/conformance/tests/httproute-partially-invalid-via-reference-grant.go b/conformance/tests/httproute-partially-invalid-via-reference-grant.go index 1869309632..c68d55a5e5 100644 --- a/conformance/tests/httproute-partially-invalid-via-reference-grant.go +++ b/conformance/tests/httproute-partially-invalid-via-reference-grant.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -50,9 +50,9 @@ var HTTPRoutePartiallyInvalidViaInvalidReferenceGrant = suite.ConformanceTest{ t.Run("HTTPRoute with BackendRef in another namespace and no ReferenceGrant covering the Service has a ResolvedRefs Condition with status False and Reason RefNotPermitted", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ - Type: string(v1beta1.RouteConditionResolvedRefs), + Type: string(v1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, - Reason: string(v1beta1.RouteReasonRefNotPermitted), + Reason: string(v1.RouteReasonRefNotPermitted), } kubernetes.HTTPRouteMustHaveCondition(t, s.Client, s.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) diff --git a/conformance/tests/httproute-partially-invalid-via-reference-grant.yaml b/conformance/tests/httproute-partially-invalid-via-reference-grant.yaml index 0d584b67e4..86d5259f8e 100644 --- a/conformance/tests/httproute-partially-invalid-via-reference-grant.yaml +++ b/conformance/tests/httproute-partially-invalid-via-reference-grant.yaml @@ -13,7 +13,7 @@ spec: kind: Service name: app-backend-v1 --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-reference-grant diff --git a/conformance/tests/httproute-path-match-order.yaml b/conformance/tests/httproute-path-match-order.yaml index 134ae21b49..5a8fee8b6d 100644 --- a/conformance/tests/httproute-path-match-order.yaml +++ b/conformance/tests/httproute-path-match-order.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: path-matching-order diff --git a/conformance/tests/httproute-query-param-matching.yaml b/conformance/tests/httproute-query-param-matching.yaml index 2b9db8141c..6411c64ab9 100644 --- a/conformance/tests/httproute-query-param-matching.yaml +++ b/conformance/tests/httproute-query-param-matching.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: query-param-matching @@ -33,7 +33,7 @@ spec: backendRefs: - name: infra-backend-v3 port: 8080 - + # Combinations with core match types. - matches: - path: @@ -68,7 +68,7 @@ spec: backendRefs: - name: infra-backend-v3 port: 8080 - + # Match of the form (cond1 AND cond2) OR (cond3 AND cond4 AND cond5) - matches: - path: @@ -89,7 +89,7 @@ spec: backendRefs: - name: infra-backend-v1 port: 8080 - + # Matches for checking precedence. - matches: - path: diff --git a/conformance/tests/httproute-redirect-host-and-status.yaml b/conformance/tests/httproute-redirect-host-and-status.yaml index c6de2465bb..57e2c09c83 100644 --- a/conformance/tests/httproute-redirect-host-and-status.yaml +++ b/conformance/tests/httproute-redirect-host-and-status.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: redirect-host-and-status diff --git a/conformance/tests/httproute-redirect-path.yaml b/conformance/tests/httproute-redirect-path.yaml index de03b06dc6..cea1e4ff51 100644 --- a/conformance/tests/httproute-redirect-path.yaml +++ b/conformance/tests/httproute-redirect-path.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: redirect-path diff --git a/conformance/tests/httproute-redirect-port-and-scheme.yaml b/conformance/tests/httproute-redirect-port-and-scheme.yaml index 1b6d72cd01..b665d7af23 100644 --- a/conformance/tests/httproute-redirect-port-and-scheme.yaml +++ b/conformance/tests/httproute-redirect-port-and-scheme.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: same-namespace-with-http-listener-on-8080 @@ -13,7 +13,7 @@ spec: namespaces: from: Same --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-route-for-listener-on-port-80 @@ -78,7 +78,7 @@ spec: port: 8443 hostname: example.org --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-route-for-listener-on-port-8080 @@ -114,7 +114,7 @@ spec: scheme: "https" hostname: example.org --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-route-for-listener-on-port-443 diff --git a/conformance/tests/httproute-redirect-port.yaml b/conformance/tests/httproute-redirect-port.yaml index 00cd300dbe..f9dd6c3fde 100644 --- a/conformance/tests/httproute-redirect-port.yaml +++ b/conformance/tests/httproute-redirect-port.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: redirect-port diff --git a/conformance/tests/httproute-redirect-scheme.yaml b/conformance/tests/httproute-redirect-scheme.yaml index ae72203569..db20aabffe 100644 --- a/conformance/tests/httproute-redirect-scheme.yaml +++ b/conformance/tests/httproute-redirect-scheme.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: redirect-scheme diff --git a/conformance/tests/httproute-reference-grant.go b/conformance/tests/httproute-reference-grant.go index 0b53fb92c5..fe7a3407c0 100644 --- a/conformance/tests/httproute-reference-grant.go +++ b/conformance/tests/httproute-reference-grant.go @@ -24,7 +24,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/gateway-api/apis/v1beta1" + v1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" diff --git a/conformance/tests/httproute-reference-grant.yaml b/conformance/tests/httproute-reference-grant.yaml index a7f73bb73e..66e21e8586 100644 --- a/conformance/tests/httproute-reference-grant.yaml +++ b/conformance/tests/httproute-reference-grant.yaml @@ -13,7 +13,7 @@ spec: kind: Service name: web-backend --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: reference-grant diff --git a/conformance/tests/httproute-request-header-modifier.yaml b/conformance/tests/httproute-request-header-modifier.yaml index ad41b16d33..c303958e62 100644 --- a/conformance/tests/httproute-request-header-modifier.yaml +++ b/conformance/tests/httproute-request-header-modifier.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: request-header-modifier diff --git a/conformance/tests/httproute-request-mirror.yaml b/conformance/tests/httproute-request-mirror.yaml index b742b795d2..4420202b9d 100644 --- a/conformance/tests/httproute-request-mirror.yaml +++ b/conformance/tests/httproute-request-mirror.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: request-mirror diff --git a/conformance/tests/httproute-request-multiple-mirrors.yaml b/conformance/tests/httproute-request-multiple-mirrors.yaml index bf2d13b356..684cf0c2d5 100644 --- a/conformance/tests/httproute-request-multiple-mirrors.yaml +++ b/conformance/tests/httproute-request-multiple-mirrors.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: request-multiple-mirrors diff --git a/conformance/tests/httproute-response-header-modifier.yaml b/conformance/tests/httproute-response-header-modifier.yaml index 68f7fc5d95..f9a76695f1 100644 --- a/conformance/tests/httproute-response-header-modifier.yaml +++ b/conformance/tests/httproute-response-header-modifier.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: response-header-modifier diff --git a/conformance/tests/httproute-rewrite-host.yaml b/conformance/tests/httproute-rewrite-host.yaml index c8a260ab68..e1db06a3e2 100644 --- a/conformance/tests/httproute-rewrite-host.yaml +++ b/conformance/tests/httproute-rewrite-host.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: rewrite-host diff --git a/conformance/tests/httproute-rewrite-path.yaml b/conformance/tests/httproute-rewrite-path.yaml index e174a60d4e..ecc4dc2e65 100644 --- a/conformance/tests/httproute-rewrite-path.yaml +++ b/conformance/tests/httproute-rewrite-path.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: rewrite-path diff --git a/conformance/tests/httproute-simple-same-namespace.yaml b/conformance/tests/httproute-simple-same-namespace.yaml index 5129a51a07..b84ee0bbf0 100644 --- a/conformance/tests/httproute-simple-same-namespace.yaml +++ b/conformance/tests/httproute-simple-same-namespace.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: gateway-conformance-infra-test diff --git a/conformance/tests/mesh-consumer-route.yaml b/conformance/tests/mesh-consumer-route.yaml index 6736ed125b..ecb757443c 100644 --- a/conformance/tests/mesh-consumer-route.yaml +++ b/conformance/tests/mesh-consumer-route.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: mesh-echo-add-header diff --git a/conformance/tests/mesh-frontend.yaml b/conformance/tests/mesh-frontend.yaml index b1dbf800c9..48ae7c838a 100644 --- a/conformance/tests/mesh-frontend.yaml +++ b/conformance/tests/mesh-frontend.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: mesh-split-v1 diff --git a/conformance/tests/mesh-ports.yaml b/conformance/tests/mesh-ports.yaml index 4ce735f8d0..0545445a8e 100644 --- a/conformance/tests/mesh-ports.yaml +++ b/conformance/tests/mesh-ports.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: mesh-split-v1 @@ -20,7 +20,7 @@ spec: - name: echo-v1 port: 80 --- -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: mesh-split-v2 diff --git a/conformance/tests/mesh-split.yaml b/conformance/tests/mesh-split.yaml index 99b95f38a3..861df1ffc6 100644 --- a/conformance/tests/mesh-split.yaml +++ b/conformance/tests/mesh-split.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: mesh-split diff --git a/conformance/utils/kubernetes/helpers.go b/conformance/utils/kubernetes/helpers.go index b970a7d959..79d83e5bd6 100644 --- a/conformance/utils/kubernetes/helpers.go +++ b/conformance/utils/kubernetes/helpers.go @@ -36,8 +36,8 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "sigs.k8s.io/controller-runtime/pkg/client" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/apis/v1alpha2" - "sigs.k8s.io/gateway-api/apis/v1beta1" "sigs.k8s.io/gateway-api/conformance/utils/config" ) @@ -51,19 +51,19 @@ const GatewayExcludedFromReadinessChecks = "gateway-api/skip-this-for-readiness" // relying on a specific api version. type GatewayRef struct { types.NamespacedName - listenerNames []*v1beta1.SectionName + listenerNames []*gatewayv1.SectionName } // NewGatewayRef creates a GatewayRef resource. ListenerNames are optional. func NewGatewayRef(nn types.NamespacedName, listenerNames ...string) GatewayRef { - var listeners []*v1beta1.SectionName + var listeners []*gatewayv1.SectionName if len(listenerNames) == 0 { listenerNames = append(listenerNames, "") } for _, listener := range listenerNames { - sectionName := v1beta1.SectionName(listener) + sectionName := gatewayv1.SectionName(listener) listeners = append(listeners, §ionName) } return GatewayRef{ @@ -91,7 +91,7 @@ func gwcMustBeAccepted(t *testing.T, c client.Client, timeoutConfig config.Timeo var controllerName string waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.GWCMustBeAccepted, true, func(ctx context.Context) (bool, error) { - gwc := &v1beta1.GatewayClass{} + gwc := &gatewayv1.GatewayClass{} err := c.Get(ctx, types.NamespacedName{Name: gwcName}, gwc) if err != nil { return false, fmt.Errorf("error fetching GatewayClass: %w", err) @@ -118,7 +118,7 @@ func GatewayMustHaveLatestConditions(t *testing.T, c client.Client, timeoutConfi t.Helper() waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.LatestObservedGenerationSet, true, func(ctx context.Context) (bool, error) { - gw := &v1beta1.Gateway{} + gw := &gatewayv1.Gateway{} err := c.Get(ctx, gwNN, gw) if err != nil { return false, fmt.Errorf("error fetching Gateway: %w", err) @@ -137,7 +137,7 @@ func GatewayMustHaveLatestConditions(t *testing.T, c client.Client, timeoutConfi // GatewayClassMustHaveLatestConditions will fail the test if there are // conditions that were not updated -func GatewayClassMustHaveLatestConditions(t *testing.T, gwc *v1beta1.GatewayClass) { +func GatewayClassMustHaveLatestConditions(t *testing.T, gwc *gatewayv1.GatewayClass) { t.Helper() if err := ConditionsHaveLatestObservedGeneration(gwc, gwc.Status.Conditions); err != nil { @@ -147,7 +147,7 @@ func GatewayClassMustHaveLatestConditions(t *testing.T, gwc *v1beta1.GatewayClas // HTTPRouteMustHaveLatestConditions will fail the test if there are // conditions that were not updated -func HTTPRouteMustHaveLatestConditions(t *testing.T, r *v1beta1.HTTPRoute) { +func HTTPRouteMustHaveLatestConditions(t *testing.T, r *gatewayv1.HTTPRoute) { t.Helper() for _, parent := range r.Status.Parents { @@ -200,7 +200,7 @@ func NamespacesMustBeReady(t *testing.T, c client.Client, timeoutConfig config.T waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.NamespacesMustBeReady, true, func(ctx context.Context) (bool, error) { for _, ns := range namespaces { - gwList := &v1beta1.GatewayList{} + gwList := &gatewayv1.GatewayList{} err := c.List(ctx, gwList, client.InNamespace(ns)) if err != nil { t.Errorf("Error listing Gateways: %v", err) @@ -219,13 +219,13 @@ func NamespacesMustBeReady(t *testing.T, c client.Client, timeoutConfig config.T } // Passing an empty string as the Reason means that any Reason will do. - if !findConditionInList(t, gw.Status.Conditions, string(v1beta1.GatewayConditionAccepted), "True", "") { + if !findConditionInList(t, gw.Status.Conditions, string(gatewayv1.GatewayConditionAccepted), "True", "") { t.Logf("%s/%s Gateway not Accepted yet", ns, gw.Name) return false, nil } // Passing an empty string as the Reason means that any Reason will do. - if !findConditionInList(t, gw.Status.Conditions, string(v1beta1.GatewayConditionProgrammed), "True", "") { + if !findConditionInList(t, gw.Status.Conditions, string(gatewayv1.GatewayConditionProgrammed), "True", "") { t.Logf("%s/%s Gateway not Programmed yet", ns, gw.Name) return false, nil } @@ -268,7 +268,7 @@ func GatewayMustHaveCondition( timeoutConfig.GatewayMustHaveCondition, true, func(ctx context.Context) (bool, error) { - gw := &v1beta1.Gateway{} + gw := &gatewayv1.Gateway{} err := client.Get(ctx, gwNN, gw) if err != nil { return false, fmt.Errorf("error fetching Gateway: %w", err) @@ -337,8 +337,8 @@ func GatewayAndHTTPRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutCo gwAddr, err := WaitForGatewayAddress(t, c, timeoutConfig, gw.NamespacedName) require.NoErrorf(t, err, "timed out waiting for Gateway address to be assigned") - ns := v1beta1.Namespace(gw.Namespace) - kind := v1beta1.Kind("Gateway") + ns := gatewayv1.Namespace(gw.Namespace) + kind := gatewayv1.Kind("Gateway") for _, routeNN := range routeNNs { namespaceRequired := true @@ -346,21 +346,21 @@ func GatewayAndHTTPRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutCo namespaceRequired = false } - var parents []v1beta1.RouteParentStatus + var parents []gatewayv1.RouteParentStatus for _, listener := range gw.listenerNames { - parents = append(parents, v1beta1.RouteParentStatus{ - ParentRef: v1beta1.ParentReference{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), + parents = append(parents, gatewayv1.RouteParentStatus{ + ParentRef: gatewayv1.ParentReference{ + Group: (*gatewayv1.Group)(&gatewayv1.GroupVersion.Group), Kind: &kind, - Name: v1beta1.ObjectName(gw.Name), + Name: gatewayv1.ObjectName(gw.Name), Namespace: &ns, SectionName: listener, }, - ControllerName: v1beta1.GatewayController(controllerName), + ControllerName: gatewayv1.GatewayController(controllerName), Conditions: []metav1.Condition{{ - Type: string(v1beta1.RouteConditionAccepted), + Type: string(gatewayv1.RouteConditionAccepted), Status: metav1.ConditionTrue, - Reason: string(v1beta1.RouteReasonAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), }}, }) } @@ -369,17 +369,17 @@ func GatewayAndHTTPRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutCo requiredListenerConditions := []metav1.Condition{ { - Type: string(v1beta1.ListenerConditionResolvedRefs), + Type: string(gatewayv1.ListenerConditionResolvedRefs), Status: metav1.ConditionTrue, Reason: "", // any reason }, { - Type: string(v1beta1.ListenerConditionAccepted), + Type: string(gatewayv1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", // any reason }, { - Type: string(v1beta1.ListenerConditionProgrammed), + Type: string(gatewayv1.ListenerConditionProgrammed), Status: metav1.ConditionTrue, Reason: "", // any reason }, @@ -396,7 +396,7 @@ func WaitForGatewayAddress(t *testing.T, client client.Client, timeoutConfig con var ipAddr, port string waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.GatewayMustHaveAddress, true, func(ctx context.Context) (bool, error) { - gw := &v1beta1.Gateway{} + gw := &gatewayv1.Gateway{} err := client.Get(ctx, gwName, gw) if err != nil { t.Logf("error fetching Gateway: %v", err) @@ -412,7 +412,7 @@ func WaitForGatewayAddress(t *testing.T, client client.Client, timeoutConfig con // TODO: Support more than IPAddress for _, address := range gw.Status.Addresses { - if address.Type != nil && *address.Type == v1beta1.IPAddressType { + if address.Type != nil && *address.Type == gatewayv1.IPAddressType { ipAddr = address.Value return true, nil } @@ -437,7 +437,7 @@ func GatewayListenersMustHaveConditions(t *testing.T, client client.Client, time defer wg.Done() waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.GatewayListenersMustHaveCondition, true, func(ctx context.Context) (bool, error) { - var gw v1beta1.Gateway + var gw gatewayv1.Gateway if err := client.Get(ctx, gwName, &gw); err != nil { return false, fmt.Errorf("error fetching Gateway: %w", err) } @@ -462,10 +462,10 @@ func GatewayListenersMustHaveConditions(t *testing.T, client client.Client, time // GatewayMustHaveZeroRoutes validates that the gateway has zero routes attached. The status // may indicate a single listener with zero attached routes or no listeners. func GatewayMustHaveZeroRoutes(t *testing.T, client client.Client, timeoutConfig config.TimeoutConfig, gwName types.NamespacedName) { - var gotStatus *v1beta1.GatewayStatus + var gotStatus *gatewayv1.GatewayStatus waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.GatewayStatusMustHaveListeners, true, func(ctx context.Context) (bool, error) { - gw := &v1beta1.Gateway{} + gw := &gatewayv1.Gateway{} err := client.Get(ctx, gwName, gw) require.NoError(t, err, "error fetching Gateway") @@ -499,10 +499,10 @@ func GatewayMustHaveZeroRoutes(t *testing.T, client client.Client, timeoutConfig func HTTPRouteMustHaveNoAcceptedParents(t *testing.T, client client.Client, timeoutConfig config.TimeoutConfig, routeName types.NamespacedName) { t.Helper() - var actual []v1beta1.RouteParentStatus + var actual []gatewayv1.RouteParentStatus emptyChecked := false waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.HTTPRouteMustNotHaveParents, true, func(ctx context.Context) (bool, error) { - route := &v1beta1.HTTPRoute{} + route := &gatewayv1.HTTPRoute{} err := client.Get(ctx, routeName, route) if err != nil { return false, fmt.Errorf("error fetching HTTPRoute: %w", err) @@ -532,7 +532,7 @@ func HTTPRouteMustHaveNoAcceptedParents(t *testing.T, client client.Client, time } return conditionsMatch(t, []metav1.Condition{{ - Type: string(v1beta1.RouteConditionAccepted), + Type: string(gatewayv1.RouteConditionAccepted), Status: "False", }}, actual[0].Conditions), nil }) @@ -542,12 +542,12 @@ func HTTPRouteMustHaveNoAcceptedParents(t *testing.T, client client.Client, time // HTTPRouteMustHaveParents waits for the specified HTTPRoute to have parents // in status that match the expected parents. This will cause the test to halt // if the specified timeout is exceeded. -func HTTPRouteMustHaveParents(t *testing.T, client client.Client, timeoutConfig config.TimeoutConfig, routeName types.NamespacedName, parents []v1beta1.RouteParentStatus, namespaceRequired bool) { +func HTTPRouteMustHaveParents(t *testing.T, client client.Client, timeoutConfig config.TimeoutConfig, routeName types.NamespacedName, parents []gatewayv1.RouteParentStatus, namespaceRequired bool) { t.Helper() - var actual []v1beta1.RouteParentStatus + var actual []gatewayv1.RouteParentStatus waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.RouteMustHaveParents, true, func(ctx context.Context) (bool, error) { - route := &v1beta1.HTTPRoute{} + route := &gatewayv1.HTTPRoute{} err := client.Get(ctx, routeName, route) if err != nil { return false, fmt.Errorf("error fetching HTTPRoute: %w", err) @@ -572,7 +572,7 @@ func HTTPRouteMustHaveParents(t *testing.T, client client.Client, timeoutConfig func TLSRouteMustHaveParents(t *testing.T, client client.Client, timeoutConfig config.TimeoutConfig, routeName types.NamespacedName, parents []v1alpha2.RouteParentStatus, namespaceRequired bool) v1alpha2.TLSRoute { t.Helper() - var actual []v1beta1.RouteParentStatus + var actual []gatewayv1.RouteParentStatus var route v1alpha2.TLSRoute waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.RouteMustHaveParents, true, func(ctx context.Context) (bool, error) { @@ -590,7 +590,7 @@ func TLSRouteMustHaveParents(t *testing.T, client client.Client, timeoutConfig c return route } -func parentsForRouteMatch(t *testing.T, routeName types.NamespacedName, expected, actual []v1beta1.RouteParentStatus, namespaceRequired bool) bool { +func parentsForRouteMatch(t *testing.T, routeName types.NamespacedName, expected, actual []gatewayv1.RouteParentStatus, namespaceRequired bool) bool { t.Helper() if len(expected) != len(actual) { @@ -635,12 +635,12 @@ func parentsForRouteMatch(t *testing.T, routeName types.NamespacedName, expected // GatewayStatusMustHaveListeners waits for the specified Gateway to have listeners // in status that match the expected listeners. This will cause the test to halt // if the specified timeout is exceeded. -func GatewayStatusMustHaveListeners(t *testing.T, client client.Client, timeoutConfig config.TimeoutConfig, gwNN types.NamespacedName, listeners []v1beta1.ListenerStatus) { +func GatewayStatusMustHaveListeners(t *testing.T, client client.Client, timeoutConfig config.TimeoutConfig, gwNN types.NamespacedName, listeners []gatewayv1.ListenerStatus) { t.Helper() - var actual []v1beta1.ListenerStatus + var actual []gatewayv1.ListenerStatus waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.GatewayStatusMustHaveListeners, true, func(ctx context.Context) (bool, error) { - gw := &v1beta1.Gateway{} + gw := &gatewayv1.Gateway{} err := client.Get(ctx, gwNN, gw) if err != nil { return false, fmt.Errorf("error fetching Gateway: %w", err) @@ -663,7 +663,7 @@ func HTTPRouteMustHaveCondition(t *testing.T, client client.Client, timeoutConfi t.Helper() waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.HTTPRouteMustHaveCondition, true, func(ctx context.Context) (bool, error) { - route := &v1beta1.HTTPRoute{} + route := &gatewayv1.HTTPRoute{} err := client.Get(ctx, routeNN, route) if err != nil { return false, fmt.Errorf("error fetching HTTPRoute: %w", err) @@ -677,7 +677,7 @@ func HTTPRouteMustHaveCondition(t *testing.T, client client.Client, timeoutConfi return false, nil } - if parent.ParentRef.Name == v1beta1.ObjectName(gwNN.Name) && (parent.ParentRef.Namespace == nil || string(*parent.ParentRef.Namespace) == gwNN.Namespace) { + if parent.ParentRef.Name == gatewayv1.ObjectName(gwNN.Name) && (parent.ParentRef.Namespace == nil || string(*parent.ParentRef.Namespace) == gwNN.Namespace) { if findConditionInList(t, parent.Conditions, condition.Type, string(condition.Status), condition.Reason) { conditionFound = true } @@ -694,13 +694,13 @@ func HTTPRouteMustHaveCondition(t *testing.T, client client.Client, timeoutConfi // set to true. func HTTPRouteMustHaveResolvedRefsConditionsTrue(t *testing.T, client client.Client, timeoutConfig config.TimeoutConfig, routeNN types.NamespacedName, gwNN types.NamespacedName) { HTTPRouteMustHaveCondition(t, client, timeoutConfig, routeNN, gwNN, metav1.Condition{ - Type: string(v1beta1.RouteConditionResolvedRefs), + Type: string(gatewayv1.RouteConditionResolvedRefs), Status: metav1.ConditionTrue, - Reason: string(v1beta1.RouteReasonResolvedRefs), + Reason: string(gatewayv1.RouteReasonResolvedRefs), }) } -func parentRefToString(p v1beta1.ParentReference) string { +func parentRefToString(p gatewayv1.ParentReference) string { if p.Namespace != nil && *p.Namespace != "" { return fmt.Sprintf("%v/%v", p.Namespace, p.Name) } @@ -711,16 +711,16 @@ func parentRefToString(p v1beta1.ParentReference) string { // address assigned to it and the TLSRoute has a ParentRef referring to the // Gateway. The test will fail if these conditions are not met before the // timeouts. -func GatewayAndTLSRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutConfig config.TimeoutConfig, controllerName string, gw GatewayRef, routeNNs ...types.NamespacedName) (string, []v1beta1.Hostname) { +func GatewayAndTLSRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutConfig config.TimeoutConfig, controllerName string, gw GatewayRef, routeNNs ...types.NamespacedName) (string, []gatewayv1.Hostname) { t.Helper() - var hostnames []v1beta1.Hostname + var hostnames []gatewayv1.Hostname gwAddr, err := WaitForGatewayAddress(t, c, timeoutConfig, gw.NamespacedName) require.NoErrorf(t, err, "timed out waiting for Gateway address to be assigned") - ns := v1beta1.Namespace(gw.Namespace) - kind := v1beta1.Kind("Gateway") + ns := gatewayv1.Namespace(gw.Namespace) + kind := gatewayv1.Kind("Gateway") for _, routeNN := range routeNNs { namespaceRequired := true @@ -728,22 +728,22 @@ func GatewayAndTLSRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutCon namespaceRequired = false } - var parents []v1beta1.RouteParentStatus + var parents []gatewayv1.RouteParentStatus for _, listener := range gw.listenerNames { - parents = append(parents, v1beta1.RouteParentStatus{ - ParentRef: v1beta1.ParentReference{ - Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), + parents = append(parents, gatewayv1.RouteParentStatus{ + ParentRef: gatewayv1.ParentReference{ + Group: (*gatewayv1.Group)(&gatewayv1.GroupVersion.Group), Kind: &kind, - Name: v1beta1.ObjectName(gw.Name), + Name: gatewayv1.ObjectName(gw.Name), Namespace: &ns, SectionName: listener, }, - ControllerName: v1beta1.GatewayController(controllerName), + ControllerName: gatewayv1.GatewayController(controllerName), Conditions: []metav1.Condition{ { - Type: string(v1beta1.RouteConditionAccepted), + Type: string(gatewayv1.RouteConditionAccepted), Status: metav1.ConditionTrue, - Reason: string(v1beta1.RouteReasonAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), }, }, }) @@ -775,7 +775,7 @@ func TLSRouteMustHaveCondition(t *testing.T, client client.Client, timeoutConfig return false, nil } - if parent.ParentRef.Name == v1beta1.ObjectName(gwNN.Name) && (parent.ParentRef.Namespace == nil || string(*parent.ParentRef.Namespace) == gwNN.Namespace) { + if parent.ParentRef.Name == gatewayv1.ObjectName(gwNN.Name) && (parent.ParentRef.Namespace == nil || string(*parent.ParentRef.Namespace) == gwNN.Namespace) { if findConditionInList(t, parent.Conditions, condition.Type, string(condition.Status), condition.Reason) { conditionFound = true } @@ -789,7 +789,7 @@ func TLSRouteMustHaveCondition(t *testing.T, client client.Client, timeoutConfig } // TODO(mikemorris): this and parentsMatch could possibly be rewritten as a generic function? -func listenersMatch(t *testing.T, expected, actual []v1beta1.ListenerStatus) bool { +func listenersMatch(t *testing.T, expected, actual []gatewayv1.ListenerStatus) bool { t.Helper() if len(expected) != len(actual) { @@ -798,7 +798,7 @@ func listenersMatch(t *testing.T, expected, actual []v1beta1.ListenerStatus) boo } for _, eListener := range expected { - var aListener *v1beta1.ListenerStatus + var aListener *gatewayv1.ListenerStatus for i := range actual { if actual[i].Name == eListener.Name { aListener = &actual[i] @@ -823,11 +823,11 @@ func listenersMatch(t *testing.T, expected, actual []v1beta1.ListenerStatus) boo for _, aKind := range aListener.SupportedKinds { if eKind.Group == nil { - eKind.Group = (*v1beta1.Group)(&v1beta1.GroupVersion.Group) + eKind.Group = (*gatewayv1.Group)(&gatewayv1.GroupVersion.Group) } if aKind.Group == nil { - aKind.Group = (*v1beta1.Group)(&v1beta1.GroupVersion.Group) + aKind.Group = (*gatewayv1.Group)(&gatewayv1.GroupVersion.Group) } if *eKind.Group == *aKind.Group && eKind.Kind == aKind.Kind { diff --git a/examples/standard/default-match-http.yaml b/examples/standard/default-match-http.yaml index 0e70dc20ad..f6b11f51f3 100644 --- a/examples/standard/default-match-http.yaml +++ b/examples/standard/default-match-http.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: default-match-example diff --git a/examples/standard/gateway-addresses.yaml b/examples/standard/gateway-addresses.yaml index bb543a422c..c2e4718aac 100644 --- a/examples/standard/gateway-addresses.yaml +++ b/examples/standard/gateway-addresses.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-addresses diff --git a/hack/invalid-examples/standard/gateway/duplicate-listeners.yaml b/hack/invalid-examples/standard/gateway/duplicate-listeners.yaml index ff306117fd..e45a4843a5 100644 --- a/hack/invalid-examples/standard/gateway/duplicate-listeners.yaml +++ b/hack/invalid-examples/standard/gateway/duplicate-listeners.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: duplicate-listeners diff --git a/hack/invalid-examples/standard/gateway/hostname-tcp.yaml b/hack/invalid-examples/standard/gateway/hostname-tcp.yaml index f635d89c9e..6e4955da45 100644 --- a/hack/invalid-examples/standard/gateway/hostname-tcp.yaml +++ b/hack/invalid-examples/standard/gateway/hostname-tcp.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: hostname-tcp diff --git a/hack/invalid-examples/standard/gateway/hostname-udp.yaml b/hack/invalid-examples/standard/gateway/hostname-udp.yaml index 1d1b5a045d..fa86944a9c 100644 --- a/hack/invalid-examples/standard/gateway/hostname-udp.yaml +++ b/hack/invalid-examples/standard/gateway/hostname-udp.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: hostname-udp diff --git a/hack/invalid-examples/standard/gateway/invalid-addresses.yaml b/hack/invalid-examples/standard/gateway/invalid-addresses.yaml index caa52c7acf..bf7b2136d0 100644 --- a/hack/invalid-examples/standard/gateway/invalid-addresses.yaml +++ b/hack/invalid-examples/standard/gateway/invalid-addresses.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: invalid-addresses diff --git a/hack/invalid-examples/standard/gateway/invalid-listener-name.yaml b/hack/invalid-examples/standard/gateway/invalid-listener-name.yaml index 31815e6b44..57cf76b530 100644 --- a/hack/invalid-examples/standard/gateway/invalid-listener-name.yaml +++ b/hack/invalid-examples/standard/gateway/invalid-listener-name.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: invalid-listener-name diff --git a/hack/invalid-examples/standard/gateway/invalid-listener-port.yaml b/hack/invalid-examples/standard/gateway/invalid-listener-port.yaml index e7546ad2d2..c5c4d6f5ae 100644 --- a/hack/invalid-examples/standard/gateway/invalid-listener-port.yaml +++ b/hack/invalid-examples/standard/gateway/invalid-listener-port.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: invalid-listener-port diff --git a/hack/invalid-examples/standard/gateway/tlsconfig-tcp.yaml b/hack/invalid-examples/standard/gateway/tlsconfig-tcp.yaml index a351b82a25..a077cd86e9 100644 --- a/hack/invalid-examples/standard/gateway/tlsconfig-tcp.yaml +++ b/hack/invalid-examples/standard/gateway/tlsconfig-tcp.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: tlsconfig-tcp diff --git a/hack/invalid-examples/standard/gatewayclass/invalid-controller.yaml b/hack/invalid-examples/standard/gatewayclass/invalid-controller.yaml index a21ffb9876..1c1fd43e77 100644 --- a/hack/invalid-examples/standard/gatewayclass/invalid-controller.yaml +++ b/hack/invalid-examples/standard/gatewayclass/invalid-controller.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: invalid-controller diff --git a/hack/invalid-examples/standard/httproute/duplicate-header-match.yaml b/hack/invalid-examples/standard/httproute/duplicate-header-match.yaml index 95d253db2b..8bac73b5a9 100644 --- a/hack/invalid-examples/standard/httproute/duplicate-header-match.yaml +++ b/hack/invalid-examples/standard/httproute/duplicate-header-match.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: duplicate-header-match diff --git a/hack/invalid-examples/standard/httproute/duplicate-query-match.yaml b/hack/invalid-examples/standard/httproute/duplicate-query-match.yaml index 2840112112..6244c4d3e4 100644 --- a/hack/invalid-examples/standard/httproute/duplicate-query-match.yaml +++ b/hack/invalid-examples/standard/httproute/duplicate-query-match.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: duplicate-query-match diff --git a/hack/invalid-examples/standard/httproute/httproute-portless-backend.yaml b/hack/invalid-examples/standard/httproute/httproute-portless-backend.yaml index f8082af21a..094ca6cbe1 100644 --- a/hack/invalid-examples/standard/httproute/httproute-portless-backend.yaml +++ b/hack/invalid-examples/standard/httproute/httproute-portless-backend.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: portless-backend diff --git a/hack/invalid-examples/standard/httproute/httproute-portless-service.yaml b/hack/invalid-examples/standard/httproute/httproute-portless-service.yaml index 59528b28f5..7a8b3f055c 100644 --- a/hack/invalid-examples/standard/httproute/httproute-portless-service.yaml +++ b/hack/invalid-examples/standard/httproute/httproute-portless-service.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: portless-service diff --git a/hack/invalid-examples/standard/httproute/invalid-backend-group.yaml b/hack/invalid-examples/standard/httproute/invalid-backend-group.yaml index c7d6a1bbf1..a9d76d569f 100644 --- a/hack/invalid-examples/standard/httproute/invalid-backend-group.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-backend-group.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-backend-group diff --git a/hack/invalid-examples/standard/httproute/invalid-backend-kind.yaml b/hack/invalid-examples/standard/httproute/invalid-backend-kind.yaml index 65cfd67b75..4c7c00de52 100644 --- a/hack/invalid-examples/standard/httproute/invalid-backend-kind.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-backend-kind.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-backend-kind diff --git a/hack/invalid-examples/standard/httproute/invalid-backend-port.yaml b/hack/invalid-examples/standard/httproute/invalid-backend-port.yaml index 80fe5f4373..fdd5716a4e 100644 --- a/hack/invalid-examples/standard/httproute/invalid-backend-port.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-backend-port.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-backend-port diff --git a/hack/invalid-examples/standard/httproute/invalid-filter-duplicate-header.yaml b/hack/invalid-examples/standard/httproute/invalid-filter-duplicate-header.yaml index 2474ee8956..105195c424 100644 --- a/hack/invalid-examples/standard/httproute/invalid-filter-duplicate-header.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-filter-duplicate-header.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-filter-duplicate-header diff --git a/hack/invalid-examples/standard/httproute/invalid-filter-duplicate.yaml b/hack/invalid-examples/standard/httproute/invalid-filter-duplicate.yaml index ba3be3fb41..6bcf5f86c9 100644 --- a/hack/invalid-examples/standard/httproute/invalid-filter-duplicate.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-filter-duplicate.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-filter-duplicate diff --git a/hack/invalid-examples/standard/httproute/invalid-filter-empty.yaml b/hack/invalid-examples/standard/httproute/invalid-filter-empty.yaml index ee682e47fc..49fe9eb5aa 100644 --- a/hack/invalid-examples/standard/httproute/invalid-filter-empty.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-filter-empty.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-filter-empty diff --git a/hack/invalid-examples/standard/httproute/invalid-filter-wrong-field.yaml b/hack/invalid-examples/standard/httproute/invalid-filter-wrong-field.yaml index 25c263f933..956d99a8d3 100644 --- a/hack/invalid-examples/standard/httproute/invalid-filter-wrong-field.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-filter-wrong-field.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-filter-wrong-field @@ -6,6 +6,6 @@ spec: rules: - filters: - type: RequestHeaderModifier - requestRedirect: + requestRedirect: port: 443 diff --git a/hack/invalid-examples/standard/httproute/invalid-header-name.yaml b/hack/invalid-examples/standard/httproute/invalid-header-name.yaml index 4b1f77da0c..f40c732a06 100644 --- a/hack/invalid-examples/standard/httproute/invalid-header-name.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-header-name.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-header-name diff --git a/hack/invalid-examples/standard/httproute/invalid-hostname.yaml b/hack/invalid-examples/standard/httproute/invalid-hostname.yaml index 55e2d8f632..0edf563657 100644 --- a/hack/invalid-examples/standard/httproute/invalid-hostname.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-hostname.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-hostname diff --git a/hack/invalid-examples/standard/httproute/invalid-httredirect-hostname.yaml b/hack/invalid-examples/standard/httproute/invalid-httredirect-hostname.yaml index 859d95a51c..b2885ec18a 100644 --- a/hack/invalid-examples/standard/httproute/invalid-httredirect-hostname.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-httredirect-hostname.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-backend-port diff --git a/hack/invalid-examples/standard/httproute/invalid-method.yaml b/hack/invalid-examples/standard/httproute/invalid-method.yaml index 22c85189de..506f347291 100644 --- a/hack/invalid-examples/standard/httproute/invalid-method.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-method.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-method diff --git a/hack/invalid-examples/standard/httproute/invalid-path-alphanum-specialchars-mix.yaml b/hack/invalid-examples/standard/httproute/invalid-path-alphanum-specialchars-mix.yaml index 7a1e34b2e7..073882142f 100644 --- a/hack/invalid-examples/standard/httproute/invalid-path-alphanum-specialchars-mix.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-path-alphanum-specialchars-mix.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-path-alphanum-specialchars-mix diff --git a/hack/invalid-examples/standard/httproute/invalid-path-specialchars.yaml b/hack/invalid-examples/standard/httproute/invalid-path-specialchars.yaml index 2d4b255791..3a43641e24 100644 --- a/hack/invalid-examples/standard/httproute/invalid-path-specialchars.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-path-specialchars.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: invalid-path-specialchars diff --git a/hack/invalid-examples/standard/httproute/invalid-request-redirect-with-backendref.yaml b/hack/invalid-examples/standard/httproute/invalid-request-redirect-with-backendref.yaml index 127463bc55..120a513a3e 100644 --- a/hack/invalid-examples/standard/httproute/invalid-request-redirect-with-backendref.yaml +++ b/hack/invalid-examples/standard/httproute/invalid-request-redirect-with-backendref.yaml @@ -1,4 +1,4 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-filter-rewrite diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index c608d6a532..e0e32c5c75 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -26,7 +26,7 @@ readonly GOMODCACHE="$(go env GOMODCACHE)" readonly GO111MODULE="on" readonly GOFLAGS="-mod=readonly" readonly GOPATH="$(mktemp -d)" -readonly MIN_REQUIRED_GO_VER="1.19" +readonly MIN_REQUIRED_GO_VER="1.20" function go_version_matches { go version | perl -ne "exit 1 unless m{go version go([0-9]+.[0-9]+)}; exit 1 if (\$1 < ${MIN_REQUIRED_GO_VER})" @@ -65,25 +65,25 @@ echo "Generating clientset at ${OUTPUT_PKG}/${CLIENTSET_PKG_NAME}" go run k8s.io/code-generator/cmd/client-gen \ --clientset-name "${CLIENTSET_NAME}" \ --input-base "" \ - --input "${APIS_PKG}/apis/v1alpha2,${APIS_PKG}/apis/v1beta1" \ + --input "${APIS_PKG}/apis/v1alpha2,${APIS_PKG}/apis/v1beta1,${APIS_PKG}/apis/v1" \ --output-package "${OUTPUT_PKG}/${CLIENTSET_PKG_NAME}" \ ${COMMON_FLAGS} echo "Generating listers at ${OUTPUT_PKG}/listers" go run k8s.io/code-generator/cmd/lister-gen \ - --input-dirs "${APIS_PKG}/apis/v1alpha2,${APIS_PKG}/apis/v1beta1" \ + --input-dirs "${APIS_PKG}/apis/v1alpha2,${APIS_PKG}/apis/v1beta1,${APIS_PKG}/apis/v1" \ --output-package "${OUTPUT_PKG}/listers" \ ${COMMON_FLAGS} echo "Generating informers at ${OUTPUT_PKG}/informers" go run k8s.io/code-generator/cmd/informer-gen \ - --input-dirs "${APIS_PKG}/apis/v1alpha2,${APIS_PKG}/apis/v1beta1" \ + --input-dirs "${APIS_PKG}/apis/v1alpha2,${APIS_PKG}/apis/v1beta1,${APIS_PKG}/apis/v1" \ --versioned-clientset-package "${OUTPUT_PKG}/${CLIENTSET_PKG_NAME}/${CLIENTSET_NAME}" \ --listers-package "${OUTPUT_PKG}/listers" \ --output-package "${OUTPUT_PKG}/informers" \ ${COMMON_FLAGS} -for VERSION in v1alpha2 v1beta1 +for VERSION in v1alpha2 v1beta1 v1 do echo "Generating ${VERSION} register at ${APIS_PKG}/apis/${VERSION}" go run k8s.io/code-generator/cmd/register-gen \ @@ -94,6 +94,6 @@ do echo "Generating ${VERSION} deepcopy at ${APIS_PKG}/apis/${VERSION}" go run sigs.k8s.io/controller-tools/cmd/controller-gen \ object:headerFile=${SCRIPT_ROOT}/hack/boilerplate/boilerplate.generatego.txt \ - paths="${APIS_PKG}/apis/${VERSION}" + paths="${APIS_PKG}/apis/${VERSION}" done diff --git a/pkg/admission/server.go b/pkg/admission/server.go index f3e21ac49b..683e0ee8e1 100644 --- a/pkg/admission/server.go +++ b/pkg/admission/server.go @@ -29,6 +29,8 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/klog/v2" + v1 "sigs.k8s.io/gateway-api/apis/v1" + v1Validation "sigs.k8s.io/gateway-api/apis/v1/validation" v1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" v1a2Validation "sigs.k8s.io/gateway-api/apis/v1alpha2/validation" v1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" @@ -58,26 +60,11 @@ var ( Version: v1alpha2.GroupVersion.Version, Resource: "tlsroutes", } - v1a2HTTPRouteGVR = meta.GroupVersionResource{ - Group: v1alpha2.SchemeGroupVersion.Group, - Version: v1alpha2.SchemeGroupVersion.Version, - Resource: "httproutes", - } v1a2GRPCRouteGVR = meta.GroupVersionResource{ Group: v1alpha2.SchemeGroupVersion.Group, Version: v1alpha2.SchemeGroupVersion.Version, Resource: "grpcroutes", } - v1a2GatewayGVR = meta.GroupVersionResource{ - Group: v1alpha2.SchemeGroupVersion.Group, - Version: v1alpha2.SchemeGroupVersion.Version, - Resource: "gateways", - } - v1a2GatewayClassGVR = meta.GroupVersionResource{ - Group: v1alpha2.SchemeGroupVersion.Group, - Version: v1alpha2.SchemeGroupVersion.Version, - Resource: "gatewayclasses", - } v1b1HTTPRouteGVR = meta.GroupVersionResource{ Group: v1beta1.SchemeGroupVersion.Group, Version: v1beta1.SchemeGroupVersion.Version, @@ -93,6 +80,21 @@ var ( Version: v1beta1.SchemeGroupVersion.Version, Resource: "gatewayclasses", } + v1HTTPRouteGVR = meta.GroupVersionResource{ + Group: v1.SchemeGroupVersion.Group, + Version: v1.SchemeGroupVersion.Version, + Resource: "httproutes", + } + v1GatewayGVR = meta.GroupVersionResource{ + Group: v1.SchemeGroupVersion.Group, + Version: v1.SchemeGroupVersion.Version, + Resource: "gateways", + } + v1GatewayClassGVR = meta.GroupVersionResource{ + Group: v1.SchemeGroupVersion.Group, + Version: v1.SchemeGroupVersion.Version, + Resource: "gatewayclasses", + } ) func log500(w http.ResponseWriter, err error) { @@ -186,14 +188,6 @@ func handleValidation(request admission.AdmissionRequest) (*admission.AdmissionR return nil, err } fieldErr = v1a2Validation.ValidateTLSRoute(&tRoute) - case v1a2HTTPRouteGVR: - var hRoute v1alpha2.HTTPRoute - _, _, err := deserializer.Decode(request.Object.Raw, nil, &hRoute) - if err != nil { - return nil, err - } - - fieldErr = v1a2Validation.ValidateHTTPRoute(&hRoute) case v1a2GRPCRouteGVR: var gRoute v1alpha2.GRPCRoute _, _, err := deserializer.Decode(request.Object.Raw, nil, &gRoute) @@ -210,13 +204,6 @@ func handleValidation(request admission.AdmissionRequest) (*admission.AdmissionR } fieldErr = v1b1Validation.ValidateHTTPRoute(&hRoute) - case v1a2GatewayGVR: - var gateway v1alpha2.Gateway - _, _, err := deserializer.Decode(request.Object.Raw, nil, &gateway) - if err != nil { - return nil, err - } - fieldErr = v1a2Validation.ValidateGateway(&gateway) case v1b1GatewayGVR: var gateway v1beta1.Gateway _, _, err := deserializer.Decode(request.Object.Raw, nil, &gateway) @@ -224,38 +211,52 @@ func handleValidation(request admission.AdmissionRequest) (*admission.AdmissionR return nil, err } fieldErr = v1b1Validation.ValidateGateway(&gateway) - case v1a2GatewayClassGVR: + case v1b1GatewayClassGVR: // runs only for updates if request.Operation != admission.Update { break } - var gatewayClass v1alpha2.GatewayClass + var gatewayClass v1beta1.GatewayClass _, _, err := deserializer.Decode(request.Object.Raw, nil, &gatewayClass) if err != nil { return nil, err } - var gatewayClassOld v1alpha2.GatewayClass + var gatewayClassOld v1beta1.GatewayClass _, _, err = deserializer.Decode(request.OldObject.Raw, nil, &gatewayClassOld) if err != nil { return nil, err } - fieldErr = v1a2Validation.ValidateGatewayClassUpdate(&gatewayClassOld, &gatewayClass) - case v1b1GatewayClassGVR: + fieldErr = v1b1Validation.ValidateGatewayClassUpdate(&gatewayClassOld, &gatewayClass) + case v1HTTPRouteGVR: + var hRoute v1.HTTPRoute + _, _, err := deserializer.Decode(request.Object.Raw, nil, &hRoute) + if err != nil { + return nil, err + } + fieldErr = v1Validation.ValidateHTTPRoute(&hRoute) + case v1GatewayGVR: + var gateway v1.Gateway + _, _, err := deserializer.Decode(request.Object.Raw, nil, &gateway) + if err != nil { + return nil, err + } + fieldErr = v1Validation.ValidateGateway(&gateway) + case v1GatewayClassGVR: // runs only for updates if request.Operation != admission.Update { break } - var gatewayClass v1beta1.GatewayClass + var gatewayClass v1.GatewayClass _, _, err := deserializer.Decode(request.Object.Raw, nil, &gatewayClass) if err != nil { return nil, err } - var gatewayClassOld v1beta1.GatewayClass + var gatewayClassOld v1.GatewayClass _, _, err = deserializer.Decode(request.OldObject.Raw, nil, &gatewayClassOld) if err != nil { return nil, err } - fieldErr = v1b1Validation.ValidateGatewayClassUpdate(&gatewayClassOld, &gatewayClass) + fieldErr = v1Validation.ValidateGatewayClassUpdate(&gatewayClassOld, &gatewayClass) default: return nil, fmt.Errorf("unknown resource '%v'", request.Resource.Resource) } diff --git a/pkg/admission/server_test.go b/pkg/admission/server_test.go index 95e4d8ec04..2d150247e9 100644 --- a/pkg/admission/server_test.go +++ b/pkg/admission/server_test.go @@ -108,11 +108,11 @@ func TestServeHTTPSubmissions(t *testing.T) { "uid": "7313cd05-eddc-4150-b88c-971a0d53b2ab", "resource": { "group": "gateway.networking.k8s.io", - "version": "v1alpha2", + "version": "v1", "resource": "httproutes" }, "object": { - "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "apiVersion": "gateway.networking.k8s.io/v1", "kind": "HTTPRoute" }, "operation": "CREATE" @@ -122,7 +122,7 @@ func TestServeHTTPSubmissions(t *testing.T) { wantFailureMessage: "submitted object is not of kind AdmissionReview\n", }, { - name: "valid v1alpha2 Gateway resource", + name: "valid v1 Gateway resource", reqBody: dedent.Dedent(`{ "kind": "AdmissionReview", "apiVersion": "` + apiVersion + `", @@ -130,12 +130,12 @@ func TestServeHTTPSubmissions(t *testing.T) { "uid": "7313cd05-eddc-4150-b88c-971a0d53b2ab", "resource": { "group": "gateway.networking.k8s.io", - "version": "v1alpha2", + "version": "v1", "resource": "gateways" }, "object": { "kind": "Gateway", - "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "apiVersion": "gateway.networking.k8s.io/v1", "metadata": { "name": "gateway-1", "labels": { @@ -171,7 +171,7 @@ func TestServeHTTPSubmissions(t *testing.T) { }, }, { - name: "valid v1alpha2 HTTPRoute resource", + name: "valid v1 HTTPRoute resource", reqBody: dedent.Dedent(`{ "kind": "AdmissionReview", "apiVersion": "` + apiVersion + `", @@ -179,12 +179,12 @@ func TestServeHTTPSubmissions(t *testing.T) { "uid": "7313cd05-eddc-4150-b88c-971a0d53b2ab", "resource": { "group": "gateway.networking.k8s.io", - "version": "v1alpha2", + "version": "v1", "resource": "httproutes" }, "object": { "kind": "HTTPRoute", - "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "apiVersion": "gateway.networking.k8s.io/v1", "metadata": { "name": "http-app-1", "labels": { @@ -235,7 +235,7 @@ func TestServeHTTPSubmissions(t *testing.T) { }, }, { - name: "valid v1alpha2 HTTPRoute resource with two request mirror filters", + name: "valid v1 HTTPRoute resource with two request mirror filters", reqBody: dedent.Dedent(`{ "kind": "AdmissionReview", "apiVersion": "` + apiVersion + `", @@ -243,12 +243,12 @@ func TestServeHTTPSubmissions(t *testing.T) { "uid": "7313cd05-eddc-4150-b88c-971a0d53b2ab", "resource": { "group": "gateway.networking.k8s.io", - "version": "v1alpha2", + "version": "v1", "resource": "httproutes" }, "object": { "kind": "HTTPRoute", - "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "apiVersion": "gateway.networking.k8s.io/v1", "metadata": { "name": "http-app-1", "labels": { @@ -314,12 +314,12 @@ func TestServeHTTPSubmissions(t *testing.T) { "uid": "7313cd05-eddc-4150-b88c-971a0d53b2ab", "resource": { "group": "gateway.networking.k8s.io", - "version": "v1alpha2", + "version": "v1", "resource": "gatewayclasses" }, "object": { "kind": "GatewayClass", - "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "apiVersion": "gateway.networking.k8s.io/v1", "metadata": { "name": "gateway-class-1" }, @@ -338,7 +338,7 @@ func TestServeHTTPSubmissions(t *testing.T) { }, }, { - name: "update to v1alpha2 GatewayClass parameters field does" + + name: "update to v1 GatewayClass parameters field does" + " not result in an error", reqBody: dedent.Dedent(`{ "kind": "AdmissionReview", @@ -347,12 +347,12 @@ func TestServeHTTPSubmissions(t *testing.T) { "uid": "7313cd05-eddc-4150-b88c-971a0d53b2ab", "resource": { "group": "gateway.networking.k8s.io", - "version": "v1alpha2", + "version": "v1", "resource": "gatewayclasses" }, "object": { "kind": "GatewayClass", - "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "apiVersion": "gateway.networking.k8s.io/v1", "metadata": { "name": "gateway-class-1" }, @@ -362,7 +362,7 @@ func TestServeHTTPSubmissions(t *testing.T) { }, "oldObject": { "kind": "GatewayClass", - "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "apiVersion": "gateway.networking.k8s.io/v1", "metadata": { "name": "gateway-class-1" }, @@ -388,7 +388,7 @@ func TestServeHTTPSubmissions(t *testing.T) { }, }, { - name: "update to v1alpha2 GatewayClass controllerName field" + + name: "update to v1 GatewayClass controllerName field" + " results in an error ", reqBody: dedent.Dedent(`{ "kind": "AdmissionReview", @@ -397,12 +397,12 @@ func TestServeHTTPSubmissions(t *testing.T) { "uid": "7313cd05-eddc-4150-b88c-971a0d53b2ab", "resource": { "group": "gateway.networking.k8s.io", - "version": "v1alpha2", + "version": "v1", "resource": "gatewayclasses" }, "object": { "kind": "GatewayClass", - "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "apiVersion": "gateway.networking.k8s.io/v1", "metadata": { "name": "gateway-class-1" }, @@ -412,7 +412,7 @@ func TestServeHTTPSubmissions(t *testing.T) { }, "oldObject": { "kind": "GatewayClass", - "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "apiVersion": "gateway.networking.k8s.io/v1", "metadata": { "name": "gateway-class-1" }, @@ -442,11 +442,11 @@ func TestServeHTTPSubmissions(t *testing.T) { "uid": "7313cd05-eddc-4150-b88c-971a0d53b2ab", "resource": { "group": "gateway.networking.k8s.io", - "version": "v1alpha2", + "version": "v1", "resource": "brokenroutes" }, "object": { - "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "apiVersion": "gateway.networking.k8s.io/v1", "kind": "HTTPRoute" }, "operation": "CREATE" diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go index 342a48d34e..743be8d8fc 100644 --- a/pkg/client/clientset/versioned/clientset.go +++ b/pkg/client/clientset/versioned/clientset.go @@ -25,6 +25,7 @@ import ( discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" + gatewayv1 "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/typed/apis/v1" gatewayv1alpha2 "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/typed/apis/v1alpha2" gatewayv1beta1 "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/typed/apis/v1beta1" ) @@ -33,6 +34,7 @@ type Interface interface { Discovery() discovery.DiscoveryInterface GatewayV1alpha2() gatewayv1alpha2.GatewayV1alpha2Interface GatewayV1beta1() gatewayv1beta1.GatewayV1beta1Interface + GatewayV1() gatewayv1.GatewayV1Interface } // Clientset contains the clients for groups. @@ -40,6 +42,7 @@ type Clientset struct { *discovery.DiscoveryClient gatewayV1alpha2 *gatewayv1alpha2.GatewayV1alpha2Client gatewayV1beta1 *gatewayv1beta1.GatewayV1beta1Client + gatewayV1 *gatewayv1.GatewayV1Client } // GatewayV1alpha2 retrieves the GatewayV1alpha2Client @@ -52,6 +55,11 @@ func (c *Clientset) GatewayV1beta1() gatewayv1beta1.GatewayV1beta1Interface { return c.gatewayV1beta1 } +// GatewayV1 retrieves the GatewayV1Client +func (c *Clientset) GatewayV1() gatewayv1.GatewayV1Interface { + return c.gatewayV1 +} + // Discovery retrieves the DiscoveryClient func (c *Clientset) Discovery() discovery.DiscoveryInterface { if c == nil { @@ -104,6 +112,10 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, if err != nil { return nil, err } + cs.gatewayV1, err = gatewayv1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) if err != nil { @@ -127,6 +139,7 @@ func New(c rest.Interface) *Clientset { var cs Clientset cs.gatewayV1alpha2 = gatewayv1alpha2.New(c) cs.gatewayV1beta1 = gatewayv1beta1.New(c) + cs.gatewayV1 = gatewayv1.New(c) cs.DiscoveryClient = discovery.NewDiscoveryClient(c) return &cs diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index 62bd300060..a3045a7102 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -25,6 +25,8 @@ import ( fakediscovery "k8s.io/client-go/discovery/fake" "k8s.io/client-go/testing" clientset "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned" + gatewayv1 "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/typed/apis/v1" + fakegatewayv1 "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/typed/apis/v1/fake" gatewayv1alpha2 "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/typed/apis/v1alpha2" fakegatewayv1alpha2 "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake" gatewayv1beta1 "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/typed/apis/v1beta1" @@ -90,3 +92,8 @@ func (c *Clientset) GatewayV1alpha2() gatewayv1alpha2.GatewayV1alpha2Interface { func (c *Clientset) GatewayV1beta1() gatewayv1beta1.GatewayV1beta1Interface { return &fakegatewayv1beta1.FakeGatewayV1beta1{Fake: &c.Fake} } + +// GatewayV1 retrieves the GatewayV1Client +func (c *Clientset) GatewayV1() gatewayv1.GatewayV1Interface { + return &fakegatewayv1.FakeGatewayV1{Fake: &c.Fake} +} diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go index 8a82c1577a..e3296a9cbd 100644 --- a/pkg/client/clientset/versioned/fake/register.go +++ b/pkg/client/clientset/versioned/fake/register.go @@ -24,6 +24,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) @@ -34,6 +35,7 @@ var codecs = serializer.NewCodecFactory(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ gatewayv1alpha2.AddToScheme, gatewayv1beta1.AddToScheme, + gatewayv1.AddToScheme, } // AddToScheme adds all types of this clientset into the given scheme. This allows composition diff --git a/pkg/client/clientset/versioned/scheme/register.go b/pkg/client/clientset/versioned/scheme/register.go index 2b7556a4e9..4d31a9ec73 100644 --- a/pkg/client/clientset/versioned/scheme/register.go +++ b/pkg/client/clientset/versioned/scheme/register.go @@ -24,6 +24,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) @@ -34,6 +35,7 @@ var ParameterCodec = runtime.NewParameterCodec(Scheme) var localSchemeBuilder = runtime.SchemeBuilder{ gatewayv1alpha2.AddToScheme, gatewayv1beta1.AddToScheme, + gatewayv1.AddToScheme, } // AddToScheme adds all types of this clientset into the given scheme. This allows composition diff --git a/pkg/client/clientset/versioned/typed/apis/v1/apis_client.go b/pkg/client/clientset/versioned/typed/apis/v1/apis_client.go new file mode 100644 index 0000000000..acc5291142 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/apis_client.go @@ -0,0 +1,117 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + rest "k8s.io/client-go/rest" + v1 "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/scheme" +) + +type GatewayV1Interface interface { + RESTClient() rest.Interface + GatewaysGetter + GatewayClassesGetter + HTTPRoutesGetter +} + +// GatewayV1Client is used to interact with features provided by the gateway.networking.k8s.io group. +type GatewayV1Client struct { + restClient rest.Interface +} + +func (c *GatewayV1Client) Gateways(namespace string) GatewayInterface { + return newGateways(c, namespace) +} + +func (c *GatewayV1Client) GatewayClasses() GatewayClassInterface { + return newGatewayClasses(c) +} + +func (c *GatewayV1Client) HTTPRoutes(namespace string) HTTPRouteInterface { + return newHTTPRoutes(c, namespace) +} + +// NewForConfig creates a new GatewayV1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*GatewayV1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new GatewayV1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*GatewayV1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &GatewayV1Client{client}, nil +} + +// NewForConfigOrDie creates a new GatewayV1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *GatewayV1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new GatewayV1Client for the given RESTClient. +func New(c rest.Interface) *GatewayV1Client { + return &GatewayV1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *GatewayV1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/client/clientset/versioned/typed/apis/v1/doc.go b/pkg/client/clientset/versioned/typed/apis/v1/doc.go new file mode 100644 index 0000000000..3af5d054f1 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1 diff --git a/pkg/client/clientset/versioned/typed/apis/v1/fake/doc.go b/pkg/client/clientset/versioned/typed/apis/v1/fake/doc.go new file mode 100644 index 0000000000..16f4439906 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_apis_client.go b/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_apis_client.go new file mode 100644 index 0000000000..290fcce3e9 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_apis_client.go @@ -0,0 +1,48 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1 "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/typed/apis/v1" +) + +type FakeGatewayV1 struct { + *testing.Fake +} + +func (c *FakeGatewayV1) Gateways(namespace string) v1.GatewayInterface { + return &FakeGateways{c, namespace} +} + +func (c *FakeGatewayV1) GatewayClasses() v1.GatewayClassInterface { + return &FakeGatewayClasses{c} +} + +func (c *FakeGatewayV1) HTTPRoutes(namespace string) v1.HTTPRouteInterface { + return &FakeHTTPRoutes{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeGatewayV1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_gateway.go b/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_gateway.go new file mode 100644 index 0000000000..5ab4e7e189 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_gateway.go @@ -0,0 +1,141 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// FakeGateways implements GatewayInterface +type FakeGateways struct { + Fake *FakeGatewayV1 + ns string +} + +var gatewaysResource = v1.SchemeGroupVersion.WithResource("gateways") + +var gatewaysKind = v1.SchemeGroupVersion.WithKind("Gateway") + +// Get takes name of the gateway, and returns the corresponding gateway object, and an error if there is any. +func (c *FakeGateways) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.Gateway, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(gatewaysResource, c.ns, name), &v1.Gateway{}) + + if obj == nil { + return nil, err + } + return obj.(*v1.Gateway), err +} + +// List takes label and field selectors, and returns the list of Gateways that match those selectors. +func (c *FakeGateways) List(ctx context.Context, opts metav1.ListOptions) (result *v1.GatewayList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(gatewaysResource, gatewaysKind, c.ns, opts), &v1.GatewayList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1.GatewayList{ListMeta: obj.(*v1.GatewayList).ListMeta} + for _, item := range obj.(*v1.GatewayList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested gateways. +func (c *FakeGateways) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(gatewaysResource, c.ns, opts)) + +} + +// Create takes the representation of a gateway and creates it. Returns the server's representation of the gateway, and an error, if there is any. +func (c *FakeGateways) Create(ctx context.Context, gateway *v1.Gateway, opts metav1.CreateOptions) (result *v1.Gateway, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(gatewaysResource, c.ns, gateway), &v1.Gateway{}) + + if obj == nil { + return nil, err + } + return obj.(*v1.Gateway), err +} + +// Update takes the representation of a gateway and updates it. Returns the server's representation of the gateway, and an error, if there is any. +func (c *FakeGateways) Update(ctx context.Context, gateway *v1.Gateway, opts metav1.UpdateOptions) (result *v1.Gateway, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(gatewaysResource, c.ns, gateway), &v1.Gateway{}) + + if obj == nil { + return nil, err + } + return obj.(*v1.Gateway), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeGateways) UpdateStatus(ctx context.Context, gateway *v1.Gateway, opts metav1.UpdateOptions) (*v1.Gateway, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(gatewaysResource, "status", c.ns, gateway), &v1.Gateway{}) + + if obj == nil { + return nil, err + } + return obj.(*v1.Gateway), err +} + +// Delete takes name of the gateway and deletes it. Returns an error if one occurs. +func (c *FakeGateways) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(gatewaysResource, c.ns, name, opts), &v1.Gateway{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeGateways) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + action := testing.NewDeleteCollectionAction(gatewaysResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1.GatewayList{}) + return err +} + +// Patch applies the patch and returns the patched gateway. +func (c *FakeGateways) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.Gateway, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(gatewaysResource, c.ns, name, pt, data, subresources...), &v1.Gateway{}) + + if obj == nil { + return nil, err + } + return obj.(*v1.Gateway), err +} diff --git a/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_gatewayclass.go b/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_gatewayclass.go new file mode 100644 index 0000000000..0d85bf47aa --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_gatewayclass.go @@ -0,0 +1,132 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// FakeGatewayClasses implements GatewayClassInterface +type FakeGatewayClasses struct { + Fake *FakeGatewayV1 +} + +var gatewayclassesResource = v1.SchemeGroupVersion.WithResource("gatewayclasses") + +var gatewayclassesKind = v1.SchemeGroupVersion.WithKind("GatewayClass") + +// Get takes name of the gatewayClass, and returns the corresponding gatewayClass object, and an error if there is any. +func (c *FakeGatewayClasses) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.GatewayClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(gatewayclassesResource, name), &v1.GatewayClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1.GatewayClass), err +} + +// List takes label and field selectors, and returns the list of GatewayClasses that match those selectors. +func (c *FakeGatewayClasses) List(ctx context.Context, opts metav1.ListOptions) (result *v1.GatewayClassList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(gatewayclassesResource, gatewayclassesKind, opts), &v1.GatewayClassList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1.GatewayClassList{ListMeta: obj.(*v1.GatewayClassList).ListMeta} + for _, item := range obj.(*v1.GatewayClassList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested gatewayClasses. +func (c *FakeGatewayClasses) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(gatewayclassesResource, opts)) +} + +// Create takes the representation of a gatewayClass and creates it. Returns the server's representation of the gatewayClass, and an error, if there is any. +func (c *FakeGatewayClasses) Create(ctx context.Context, gatewayClass *v1.GatewayClass, opts metav1.CreateOptions) (result *v1.GatewayClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(gatewayclassesResource, gatewayClass), &v1.GatewayClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1.GatewayClass), err +} + +// Update takes the representation of a gatewayClass and updates it. Returns the server's representation of the gatewayClass, and an error, if there is any. +func (c *FakeGatewayClasses) Update(ctx context.Context, gatewayClass *v1.GatewayClass, opts metav1.UpdateOptions) (result *v1.GatewayClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(gatewayclassesResource, gatewayClass), &v1.GatewayClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1.GatewayClass), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeGatewayClasses) UpdateStatus(ctx context.Context, gatewayClass *v1.GatewayClass, opts metav1.UpdateOptions) (*v1.GatewayClass, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(gatewayclassesResource, "status", gatewayClass), &v1.GatewayClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1.GatewayClass), err +} + +// Delete takes name of the gatewayClass and deletes it. Returns an error if one occurs. +func (c *FakeGatewayClasses) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteActionWithOptions(gatewayclassesResource, name, opts), &v1.GatewayClass{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeGatewayClasses) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(gatewayclassesResource, listOpts) + + _, err := c.Fake.Invokes(action, &v1.GatewayClassList{}) + return err +} + +// Patch applies the patch and returns the patched gatewayClass. +func (c *FakeGatewayClasses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.GatewayClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(gatewayclassesResource, name, pt, data, subresources...), &v1.GatewayClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1.GatewayClass), err +} diff --git a/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_httproute.go b/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_httproute.go new file mode 100644 index 0000000000..7bf8647720 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_httproute.go @@ -0,0 +1,141 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// FakeHTTPRoutes implements HTTPRouteInterface +type FakeHTTPRoutes struct { + Fake *FakeGatewayV1 + ns string +} + +var httproutesResource = v1.SchemeGroupVersion.WithResource("httproutes") + +var httproutesKind = v1.SchemeGroupVersion.WithKind("HTTPRoute") + +// Get takes name of the hTTPRoute, and returns the corresponding hTTPRoute object, and an error if there is any. +func (c *FakeHTTPRoutes) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.HTTPRoute, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(httproutesResource, c.ns, name), &v1.HTTPRoute{}) + + if obj == nil { + return nil, err + } + return obj.(*v1.HTTPRoute), err +} + +// List takes label and field selectors, and returns the list of HTTPRoutes that match those selectors. +func (c *FakeHTTPRoutes) List(ctx context.Context, opts metav1.ListOptions) (result *v1.HTTPRouteList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(httproutesResource, httproutesKind, c.ns, opts), &v1.HTTPRouteList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1.HTTPRouteList{ListMeta: obj.(*v1.HTTPRouteList).ListMeta} + for _, item := range obj.(*v1.HTTPRouteList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested hTTPRoutes. +func (c *FakeHTTPRoutes) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(httproutesResource, c.ns, opts)) + +} + +// Create takes the representation of a hTTPRoute and creates it. Returns the server's representation of the hTTPRoute, and an error, if there is any. +func (c *FakeHTTPRoutes) Create(ctx context.Context, hTTPRoute *v1.HTTPRoute, opts metav1.CreateOptions) (result *v1.HTTPRoute, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(httproutesResource, c.ns, hTTPRoute), &v1.HTTPRoute{}) + + if obj == nil { + return nil, err + } + return obj.(*v1.HTTPRoute), err +} + +// Update takes the representation of a hTTPRoute and updates it. Returns the server's representation of the hTTPRoute, and an error, if there is any. +func (c *FakeHTTPRoutes) Update(ctx context.Context, hTTPRoute *v1.HTTPRoute, opts metav1.UpdateOptions) (result *v1.HTTPRoute, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(httproutesResource, c.ns, hTTPRoute), &v1.HTTPRoute{}) + + if obj == nil { + return nil, err + } + return obj.(*v1.HTTPRoute), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeHTTPRoutes) UpdateStatus(ctx context.Context, hTTPRoute *v1.HTTPRoute, opts metav1.UpdateOptions) (*v1.HTTPRoute, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(httproutesResource, "status", c.ns, hTTPRoute), &v1.HTTPRoute{}) + + if obj == nil { + return nil, err + } + return obj.(*v1.HTTPRoute), err +} + +// Delete takes name of the hTTPRoute and deletes it. Returns an error if one occurs. +func (c *FakeHTTPRoutes) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(httproutesResource, c.ns, name, opts), &v1.HTTPRoute{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeHTTPRoutes) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + action := testing.NewDeleteCollectionAction(httproutesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1.HTTPRouteList{}) + return err +} + +// Patch applies the patch and returns the patched hTTPRoute. +func (c *FakeHTTPRoutes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.HTTPRoute, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(httproutesResource, c.ns, name, pt, data, subresources...), &v1.HTTPRoute{}) + + if obj == nil { + return nil, err + } + return obj.(*v1.HTTPRoute), err +} diff --git a/pkg/client/clientset/versioned/typed/apis/v1/gateway.go b/pkg/client/clientset/versioned/typed/apis/v1/gateway.go new file mode 100644 index 0000000000..37a78cfce8 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/gateway.go @@ -0,0 +1,195 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1 "sigs.k8s.io/gateway-api/apis/v1" + scheme "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/scheme" +) + +// GatewaysGetter has a method to return a GatewayInterface. +// A group's client should implement this interface. +type GatewaysGetter interface { + Gateways(namespace string) GatewayInterface +} + +// GatewayInterface has methods to work with Gateway resources. +type GatewayInterface interface { + Create(ctx context.Context, gateway *v1.Gateway, opts metav1.CreateOptions) (*v1.Gateway, error) + Update(ctx context.Context, gateway *v1.Gateway, opts metav1.UpdateOptions) (*v1.Gateway, error) + UpdateStatus(ctx context.Context, gateway *v1.Gateway, opts metav1.UpdateOptions) (*v1.Gateway, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.Gateway, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.GatewayList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.Gateway, err error) + GatewayExpansion +} + +// gateways implements GatewayInterface +type gateways struct { + client rest.Interface + ns string +} + +// newGateways returns a Gateways +func newGateways(c *GatewayV1Client, namespace string) *gateways { + return &gateways{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the gateway, and returns the corresponding gateway object, and an error if there is any. +func (c *gateways) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.Gateway, err error) { + result = &v1.Gateway{} + err = c.client.Get(). + Namespace(c.ns). + Resource("gateways"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Gateways that match those selectors. +func (c *gateways) List(ctx context.Context, opts metav1.ListOptions) (result *v1.GatewayList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.GatewayList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("gateways"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested gateways. +func (c *gateways) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("gateways"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a gateway and creates it. Returns the server's representation of the gateway, and an error, if there is any. +func (c *gateways) Create(ctx context.Context, gateway *v1.Gateway, opts metav1.CreateOptions) (result *v1.Gateway, err error) { + result = &v1.Gateway{} + err = c.client.Post(). + Namespace(c.ns). + Resource("gateways"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(gateway). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a gateway and updates it. Returns the server's representation of the gateway, and an error, if there is any. +func (c *gateways) Update(ctx context.Context, gateway *v1.Gateway, opts metav1.UpdateOptions) (result *v1.Gateway, err error) { + result = &v1.Gateway{} + err = c.client.Put(). + Namespace(c.ns). + Resource("gateways"). + Name(gateway.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(gateway). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *gateways) UpdateStatus(ctx context.Context, gateway *v1.Gateway, opts metav1.UpdateOptions) (result *v1.Gateway, err error) { + result = &v1.Gateway{} + err = c.client.Put(). + Namespace(c.ns). + Resource("gateways"). + Name(gateway.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(gateway). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the gateway and deletes it. Returns an error if one occurs. +func (c *gateways) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("gateways"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *gateways) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("gateways"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched gateway. +func (c *gateways) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.Gateway, err error) { + result = &v1.Gateway{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("gateways"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/apis/v1/gatewayclass.go b/pkg/client/clientset/versioned/typed/apis/v1/gatewayclass.go new file mode 100644 index 0000000000..929bd9d2d8 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/gatewayclass.go @@ -0,0 +1,184 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1 "sigs.k8s.io/gateway-api/apis/v1" + scheme "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/scheme" +) + +// GatewayClassesGetter has a method to return a GatewayClassInterface. +// A group's client should implement this interface. +type GatewayClassesGetter interface { + GatewayClasses() GatewayClassInterface +} + +// GatewayClassInterface has methods to work with GatewayClass resources. +type GatewayClassInterface interface { + Create(ctx context.Context, gatewayClass *v1.GatewayClass, opts metav1.CreateOptions) (*v1.GatewayClass, error) + Update(ctx context.Context, gatewayClass *v1.GatewayClass, opts metav1.UpdateOptions) (*v1.GatewayClass, error) + UpdateStatus(ctx context.Context, gatewayClass *v1.GatewayClass, opts metav1.UpdateOptions) (*v1.GatewayClass, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.GatewayClass, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.GatewayClassList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.GatewayClass, err error) + GatewayClassExpansion +} + +// gatewayClasses implements GatewayClassInterface +type gatewayClasses struct { + client rest.Interface +} + +// newGatewayClasses returns a GatewayClasses +func newGatewayClasses(c *GatewayV1Client) *gatewayClasses { + return &gatewayClasses{ + client: c.RESTClient(), + } +} + +// Get takes name of the gatewayClass, and returns the corresponding gatewayClass object, and an error if there is any. +func (c *gatewayClasses) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.GatewayClass, err error) { + result = &v1.GatewayClass{} + err = c.client.Get(). + Resource("gatewayclasses"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of GatewayClasses that match those selectors. +func (c *gatewayClasses) List(ctx context.Context, opts metav1.ListOptions) (result *v1.GatewayClassList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.GatewayClassList{} + err = c.client.Get(). + Resource("gatewayclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested gatewayClasses. +func (c *gatewayClasses) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("gatewayclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a gatewayClass and creates it. Returns the server's representation of the gatewayClass, and an error, if there is any. +func (c *gatewayClasses) Create(ctx context.Context, gatewayClass *v1.GatewayClass, opts metav1.CreateOptions) (result *v1.GatewayClass, err error) { + result = &v1.GatewayClass{} + err = c.client.Post(). + Resource("gatewayclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(gatewayClass). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a gatewayClass and updates it. Returns the server's representation of the gatewayClass, and an error, if there is any. +func (c *gatewayClasses) Update(ctx context.Context, gatewayClass *v1.GatewayClass, opts metav1.UpdateOptions) (result *v1.GatewayClass, err error) { + result = &v1.GatewayClass{} + err = c.client.Put(). + Resource("gatewayclasses"). + Name(gatewayClass.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(gatewayClass). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *gatewayClasses) UpdateStatus(ctx context.Context, gatewayClass *v1.GatewayClass, opts metav1.UpdateOptions) (result *v1.GatewayClass, err error) { + result = &v1.GatewayClass{} + err = c.client.Put(). + Resource("gatewayclasses"). + Name(gatewayClass.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(gatewayClass). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the gatewayClass and deletes it. Returns an error if one occurs. +func (c *gatewayClasses) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Resource("gatewayclasses"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *gatewayClasses) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("gatewayclasses"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched gatewayClass. +func (c *gatewayClasses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.GatewayClass, err error) { + result = &v1.GatewayClass{} + err = c.client.Patch(pt). + Resource("gatewayclasses"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/apis/v1/generated_expansion.go b/pkg/client/clientset/versioned/typed/apis/v1/generated_expansion.go new file mode 100644 index 0000000000..bf1da7c1a4 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/generated_expansion.go @@ -0,0 +1,25 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +type GatewayExpansion interface{} + +type GatewayClassExpansion interface{} + +type HTTPRouteExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/apis/v1/httproute.go b/pkg/client/clientset/versioned/typed/apis/v1/httproute.go new file mode 100644 index 0000000000..6125934503 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/httproute.go @@ -0,0 +1,195 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1 "sigs.k8s.io/gateway-api/apis/v1" + scheme "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/scheme" +) + +// HTTPRoutesGetter has a method to return a HTTPRouteInterface. +// A group's client should implement this interface. +type HTTPRoutesGetter interface { + HTTPRoutes(namespace string) HTTPRouteInterface +} + +// HTTPRouteInterface has methods to work with HTTPRoute resources. +type HTTPRouteInterface interface { + Create(ctx context.Context, hTTPRoute *v1.HTTPRoute, opts metav1.CreateOptions) (*v1.HTTPRoute, error) + Update(ctx context.Context, hTTPRoute *v1.HTTPRoute, opts metav1.UpdateOptions) (*v1.HTTPRoute, error) + UpdateStatus(ctx context.Context, hTTPRoute *v1.HTTPRoute, opts metav1.UpdateOptions) (*v1.HTTPRoute, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.HTTPRoute, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.HTTPRouteList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.HTTPRoute, err error) + HTTPRouteExpansion +} + +// hTTPRoutes implements HTTPRouteInterface +type hTTPRoutes struct { + client rest.Interface + ns string +} + +// newHTTPRoutes returns a HTTPRoutes +func newHTTPRoutes(c *GatewayV1Client, namespace string) *hTTPRoutes { + return &hTTPRoutes{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the hTTPRoute, and returns the corresponding hTTPRoute object, and an error if there is any. +func (c *hTTPRoutes) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.HTTPRoute, err error) { + result = &v1.HTTPRoute{} + err = c.client.Get(). + Namespace(c.ns). + Resource("httproutes"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of HTTPRoutes that match those selectors. +func (c *hTTPRoutes) List(ctx context.Context, opts metav1.ListOptions) (result *v1.HTTPRouteList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.HTTPRouteList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("httproutes"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested hTTPRoutes. +func (c *hTTPRoutes) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("httproutes"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a hTTPRoute and creates it. Returns the server's representation of the hTTPRoute, and an error, if there is any. +func (c *hTTPRoutes) Create(ctx context.Context, hTTPRoute *v1.HTTPRoute, opts metav1.CreateOptions) (result *v1.HTTPRoute, err error) { + result = &v1.HTTPRoute{} + err = c.client.Post(). + Namespace(c.ns). + Resource("httproutes"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(hTTPRoute). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a hTTPRoute and updates it. Returns the server's representation of the hTTPRoute, and an error, if there is any. +func (c *hTTPRoutes) Update(ctx context.Context, hTTPRoute *v1.HTTPRoute, opts metav1.UpdateOptions) (result *v1.HTTPRoute, err error) { + result = &v1.HTTPRoute{} + err = c.client.Put(). + Namespace(c.ns). + Resource("httproutes"). + Name(hTTPRoute.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(hTTPRoute). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *hTTPRoutes) UpdateStatus(ctx context.Context, hTTPRoute *v1.HTTPRoute, opts metav1.UpdateOptions) (result *v1.HTTPRoute, err error) { + result = &v1.HTTPRoute{} + err = c.client.Put(). + Namespace(c.ns). + Resource("httproutes"). + Name(hTTPRoute.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(hTTPRoute). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the hTTPRoute and deletes it. Returns an error if one occurs. +func (c *hTTPRoutes) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("httproutes"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *hTTPRoutes) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("httproutes"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched hTTPRoute. +func (c *hTTPRoutes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.HTTPRoute, err error) { + result = &v1.HTTPRoute{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("httproutes"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/informers/externalversions/apis/interface.go b/pkg/client/informers/externalversions/apis/interface.go index 7d37107085..05de6bbe33 100644 --- a/pkg/client/informers/externalversions/apis/interface.go +++ b/pkg/client/informers/externalversions/apis/interface.go @@ -19,6 +19,7 @@ limitations under the License. package apis import ( + v1 "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/apis/v1" v1alpha2 "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/apis/v1alpha2" v1beta1 "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/apis/v1beta1" internalinterfaces "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/internalinterfaces" @@ -30,6 +31,8 @@ type Interface interface { V1alpha2() v1alpha2.Interface // V1beta1 provides access to shared informers for resources in V1beta1. V1beta1() v1beta1.Interface + // V1 provides access to shared informers for resources in V1. + V1() v1.Interface } type group struct { @@ -52,3 +55,8 @@ func (g *group) V1alpha2() v1alpha2.Interface { func (g *group) V1beta1() v1beta1.Interface { return v1beta1.New(g.factory, g.namespace, g.tweakListOptions) } + +// V1 returns a new v1.Interface. +func (g *group) V1() v1.Interface { + return v1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/client/informers/externalversions/apis/v1/gateway.go b/pkg/client/informers/externalversions/apis/v1/gateway.go new file mode 100644 index 0000000000..640db80586 --- /dev/null +++ b/pkg/client/informers/externalversions/apis/v1/gateway.go @@ -0,0 +1,90 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + apisv1 "sigs.k8s.io/gateway-api/apis/v1" + versioned "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned" + internalinterfaces "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/internalinterfaces" + v1 "sigs.k8s.io/gateway-api/pkg/client/listers/apis/v1" +) + +// GatewayInformer provides access to a shared informer and lister for +// Gateways. +type GatewayInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.GatewayLister +} + +type gatewayInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewGatewayInformer constructs a new informer for Gateway type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewGatewayInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredGatewayInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredGatewayInformer constructs a new informer for Gateway type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredGatewayInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().Gateways(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().Gateways(namespace).Watch(context.TODO(), options) + }, + }, + &apisv1.Gateway{}, + resyncPeriod, + indexers, + ) +} + +func (f *gatewayInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredGatewayInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *gatewayInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apisv1.Gateway{}, f.defaultInformer) +} + +func (f *gatewayInformer) Lister() v1.GatewayLister { + return v1.NewGatewayLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/apis/v1/gatewayclass.go b/pkg/client/informers/externalversions/apis/v1/gatewayclass.go new file mode 100644 index 0000000000..4b2a2577c6 --- /dev/null +++ b/pkg/client/informers/externalversions/apis/v1/gatewayclass.go @@ -0,0 +1,89 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + apisv1 "sigs.k8s.io/gateway-api/apis/v1" + versioned "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned" + internalinterfaces "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/internalinterfaces" + v1 "sigs.k8s.io/gateway-api/pkg/client/listers/apis/v1" +) + +// GatewayClassInformer provides access to a shared informer and lister for +// GatewayClasses. +type GatewayClassInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.GatewayClassLister +} + +type gatewayClassInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewGatewayClassInformer constructs a new informer for GatewayClass type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewGatewayClassInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredGatewayClassInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredGatewayClassInformer constructs a new informer for GatewayClass type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredGatewayClassInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().GatewayClasses().List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().GatewayClasses().Watch(context.TODO(), options) + }, + }, + &apisv1.GatewayClass{}, + resyncPeriod, + indexers, + ) +} + +func (f *gatewayClassInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredGatewayClassInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *gatewayClassInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apisv1.GatewayClass{}, f.defaultInformer) +} + +func (f *gatewayClassInformer) Lister() v1.GatewayClassLister { + return v1.NewGatewayClassLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/apis/v1/httproute.go b/pkg/client/informers/externalversions/apis/v1/httproute.go new file mode 100644 index 0000000000..921404311f --- /dev/null +++ b/pkg/client/informers/externalversions/apis/v1/httproute.go @@ -0,0 +1,90 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + apisv1 "sigs.k8s.io/gateway-api/apis/v1" + versioned "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned" + internalinterfaces "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/internalinterfaces" + v1 "sigs.k8s.io/gateway-api/pkg/client/listers/apis/v1" +) + +// HTTPRouteInformer provides access to a shared informer and lister for +// HTTPRoutes. +type HTTPRouteInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.HTTPRouteLister +} + +type hTTPRouteInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewHTTPRouteInformer constructs a new informer for HTTPRoute type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewHTTPRouteInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredHTTPRouteInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredHTTPRouteInformer constructs a new informer for HTTPRoute type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredHTTPRouteInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().HTTPRoutes(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().HTTPRoutes(namespace).Watch(context.TODO(), options) + }, + }, + &apisv1.HTTPRoute{}, + resyncPeriod, + indexers, + ) +} + +func (f *hTTPRouteInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredHTTPRouteInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *hTTPRouteInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apisv1.HTTPRoute{}, f.defaultInformer) +} + +func (f *hTTPRouteInformer) Lister() v1.HTTPRouteLister { + return v1.NewHTTPRouteLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/apis/v1/interface.go b/pkg/client/informers/externalversions/apis/v1/interface.go new file mode 100644 index 0000000000..74c823c199 --- /dev/null +++ b/pkg/client/informers/externalversions/apis/v1/interface.go @@ -0,0 +1,59 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + internalinterfaces "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // Gateways returns a GatewayInformer. + Gateways() GatewayInformer + // GatewayClasses returns a GatewayClassInformer. + GatewayClasses() GatewayClassInformer + // HTTPRoutes returns a HTTPRouteInformer. + HTTPRoutes() HTTPRouteInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// Gateways returns a GatewayInformer. +func (v *version) Gateways() GatewayInformer { + return &gatewayInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// GatewayClasses returns a GatewayClassInformer. +func (v *version) GatewayClasses() GatewayClassInformer { + return &gatewayClassInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// HTTPRoutes returns a HTTPRouteInformer. +func (v *version) HTTPRoutes() HTTPRouteInformer { + return &hTTPRouteInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index d45d346642..20f69bf8fc 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -23,6 +23,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" + v1 "sigs.k8s.io/gateway-api/apis/v1" v1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" v1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) @@ -53,7 +54,15 @@ func (f *genericInformer) Lister() cache.GenericLister { // TODO extend this to unknown resources with a client pool func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { - // Group=gateway.networking.k8s.io, Version=v1alpha2 + // Group=gateway.networking.k8s.io, Version=v1 + case v1.SchemeGroupVersion.WithResource("gateways"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1().Gateways().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("gatewayclasses"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1().GatewayClasses().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("httproutes"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1().HTTPRoutes().Informer()}, nil + + // Group=gateway.networking.k8s.io, Version=v1alpha2 case v1alpha2.SchemeGroupVersion.WithResource("backendtlspolicies"): return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1alpha2().BackendTLSPolicies().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("grpcroutes"): diff --git a/pkg/client/listers/apis/v1/expansion_generated.go b/pkg/client/listers/apis/v1/expansion_generated.go new file mode 100644 index 0000000000..910136e219 --- /dev/null +++ b/pkg/client/listers/apis/v1/expansion_generated.go @@ -0,0 +1,39 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +// GatewayListerExpansion allows custom methods to be added to +// GatewayLister. +type GatewayListerExpansion interface{} + +// GatewayNamespaceListerExpansion allows custom methods to be added to +// GatewayNamespaceLister. +type GatewayNamespaceListerExpansion interface{} + +// GatewayClassListerExpansion allows custom methods to be added to +// GatewayClassLister. +type GatewayClassListerExpansion interface{} + +// HTTPRouteListerExpansion allows custom methods to be added to +// HTTPRouteLister. +type HTTPRouteListerExpansion interface{} + +// HTTPRouteNamespaceListerExpansion allows custom methods to be added to +// HTTPRouteNamespaceLister. +type HTTPRouteNamespaceListerExpansion interface{} diff --git a/pkg/client/listers/apis/v1/gateway.go b/pkg/client/listers/apis/v1/gateway.go new file mode 100644 index 0000000000..82a886c86c --- /dev/null +++ b/pkg/client/listers/apis/v1/gateway.go @@ -0,0 +1,99 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// GatewayLister helps list Gateways. +// All objects returned here must be treated as read-only. +type GatewayLister interface { + // List lists all Gateways in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.Gateway, err error) + // Gateways returns an object that can list and get Gateways. + Gateways(namespace string) GatewayNamespaceLister + GatewayListerExpansion +} + +// gatewayLister implements the GatewayLister interface. +type gatewayLister struct { + indexer cache.Indexer +} + +// NewGatewayLister returns a new GatewayLister. +func NewGatewayLister(indexer cache.Indexer) GatewayLister { + return &gatewayLister{indexer: indexer} +} + +// List lists all Gateways in the indexer. +func (s *gatewayLister) List(selector labels.Selector) (ret []*v1.Gateway, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.Gateway)) + }) + return ret, err +} + +// Gateways returns an object that can list and get Gateways. +func (s *gatewayLister) Gateways(namespace string) GatewayNamespaceLister { + return gatewayNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// GatewayNamespaceLister helps list and get Gateways. +// All objects returned here must be treated as read-only. +type GatewayNamespaceLister interface { + // List lists all Gateways in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.Gateway, err error) + // Get retrieves the Gateway from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.Gateway, error) + GatewayNamespaceListerExpansion +} + +// gatewayNamespaceLister implements the GatewayNamespaceLister +// interface. +type gatewayNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Gateways in the indexer for a given namespace. +func (s gatewayNamespaceLister) List(selector labels.Selector) (ret []*v1.Gateway, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.Gateway)) + }) + return ret, err +} + +// Get retrieves the Gateway from the indexer for a given namespace and name. +func (s gatewayNamespaceLister) Get(name string) (*v1.Gateway, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("gateway"), name) + } + return obj.(*v1.Gateway), nil +} diff --git a/pkg/client/listers/apis/v1/gatewayclass.go b/pkg/client/listers/apis/v1/gatewayclass.go new file mode 100644 index 0000000000..e3ddf47e27 --- /dev/null +++ b/pkg/client/listers/apis/v1/gatewayclass.go @@ -0,0 +1,68 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// GatewayClassLister helps list GatewayClasses. +// All objects returned here must be treated as read-only. +type GatewayClassLister interface { + // List lists all GatewayClasses in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.GatewayClass, err error) + // Get retrieves the GatewayClass from the index for a given name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.GatewayClass, error) + GatewayClassListerExpansion +} + +// gatewayClassLister implements the GatewayClassLister interface. +type gatewayClassLister struct { + indexer cache.Indexer +} + +// NewGatewayClassLister returns a new GatewayClassLister. +func NewGatewayClassLister(indexer cache.Indexer) GatewayClassLister { + return &gatewayClassLister{indexer: indexer} +} + +// List lists all GatewayClasses in the indexer. +func (s *gatewayClassLister) List(selector labels.Selector) (ret []*v1.GatewayClass, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.GatewayClass)) + }) + return ret, err +} + +// Get retrieves the GatewayClass from the index for a given name. +func (s *gatewayClassLister) Get(name string) (*v1.GatewayClass, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("gatewayclass"), name) + } + return obj.(*v1.GatewayClass), nil +} diff --git a/pkg/client/listers/apis/v1/httproute.go b/pkg/client/listers/apis/v1/httproute.go new file mode 100644 index 0000000000..edf16efc5f --- /dev/null +++ b/pkg/client/listers/apis/v1/httproute.go @@ -0,0 +1,99 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// HTTPRouteLister helps list HTTPRoutes. +// All objects returned here must be treated as read-only. +type HTTPRouteLister interface { + // List lists all HTTPRoutes in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.HTTPRoute, err error) + // HTTPRoutes returns an object that can list and get HTTPRoutes. + HTTPRoutes(namespace string) HTTPRouteNamespaceLister + HTTPRouteListerExpansion +} + +// hTTPRouteLister implements the HTTPRouteLister interface. +type hTTPRouteLister struct { + indexer cache.Indexer +} + +// NewHTTPRouteLister returns a new HTTPRouteLister. +func NewHTTPRouteLister(indexer cache.Indexer) HTTPRouteLister { + return &hTTPRouteLister{indexer: indexer} +} + +// List lists all HTTPRoutes in the indexer. +func (s *hTTPRouteLister) List(selector labels.Selector) (ret []*v1.HTTPRoute, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.HTTPRoute)) + }) + return ret, err +} + +// HTTPRoutes returns an object that can list and get HTTPRoutes. +func (s *hTTPRouteLister) HTTPRoutes(namespace string) HTTPRouteNamespaceLister { + return hTTPRouteNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// HTTPRouteNamespaceLister helps list and get HTTPRoutes. +// All objects returned here must be treated as read-only. +type HTTPRouteNamespaceLister interface { + // List lists all HTTPRoutes in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.HTTPRoute, err error) + // Get retrieves the HTTPRoute from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.HTTPRoute, error) + HTTPRouteNamespaceListerExpansion +} + +// hTTPRouteNamespaceLister implements the HTTPRouteNamespaceLister +// interface. +type hTTPRouteNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all HTTPRoutes in the indexer for a given namespace. +func (s hTTPRouteNamespaceLister) List(selector labels.Selector) (ret []*v1.HTTPRoute, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.HTTPRoute)) + }) + return ret, err +} + +// Get retrieves the HTTPRoute from the indexer for a given namespace and name. +func (s hTTPRouteNamespaceLister) Get(name string) (*v1.HTTPRoute, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("httproute"), name) + } + return obj.(*v1.HTTPRoute), nil +} diff --git a/pkg/generator/main.go b/pkg/generator/main.go index f19676f659..ceeb5b19a6 100644 --- a/pkg/generator/main.go +++ b/pkg/generator/main.go @@ -35,8 +35,8 @@ const ( channelAnnotation = "gateway.networking.k8s.io/channel" // These values must be updated during the release process - bundleVersion = "v0.8.0" - approvalLink = "https://github.com/kubernetes-sigs/gateway-api/pull/2245" + bundleVersion = "v1.0.0-rc1" + approvalLink = "https://github.com/kubernetes-sigs/gateway-api/pull/2466" ) var standardKinds = map[string]bool{ @@ -53,6 +53,7 @@ func main() { "k8s.io/apimachinery/pkg/runtime/schema", // Needed to parse generated register functions. "sigs.k8s.io/gateway-api/apis/v1alpha2", "sigs.k8s.io/gateway-api/apis/v1beta1", + "sigs.k8s.io/gateway-api/apis/v1", ) if err != nil { log.Fatalf("failed to load package roots: %s", err) diff --git a/pkg/test/cel/gateway_test.go b/pkg/test/cel/gateway_test.go index 053c6f2692..900b033549 100644 --- a/pkg/test/cel/gateway_test.go +++ b/pkg/test/cel/gateway_test.go @@ -23,25 +23,25 @@ import ( "testing" "time" - gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestValidateGateway(t *testing.T) { ctx := context.Background() - baseGateway := gatewayv1b1.Gateway{ + baseGateway := gatewayv1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", Namespace: metav1.NamespaceDefault, }, - Spec: gatewayv1b1.GatewaySpec{ + Spec: gatewayv1.GatewaySpec{ GatewayClassName: "foo", - Listeners: []gatewayv1b1.Listener{ + Listeners: []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("http"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(80), + Name: gatewayv1.SectionName("http"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(80), }, }, }, @@ -49,19 +49,19 @@ func TestValidateGateway(t *testing.T) { testCases := []struct { desc string - mutate func(gw *gatewayv1b1.Gateway) - mutateStatus func(gw *gatewayv1b1.Gateway) + mutate func(gw *gatewayv1.Gateway) + mutateStatus func(gw *gatewayv1.Gateway) wantErrors []string }{ { desc: "tls config present with http protocol", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("http"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(8080), - TLS: &gatewayv1b1.GatewayTLSConfig{}, + Name: gatewayv1.SectionName("http"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(8080), + TLS: &gatewayv1.GatewayTLSConfig{}, }, } }, @@ -69,13 +69,13 @@ func TestValidateGateway(t *testing.T) { }, { desc: "tls config present with tcp protocol", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("tcp"), - Protocol: gatewayv1b1.TCPProtocolType, - Port: gatewayv1b1.PortNumber(8080), - TLS: &gatewayv1b1.GatewayTLSConfig{}, + Name: gatewayv1.SectionName("tcp"), + Protocol: gatewayv1.TCPProtocolType, + Port: gatewayv1.PortNumber(8080), + TLS: &gatewayv1.GatewayTLSConfig{}, }, } }, @@ -83,12 +83,12 @@ func TestValidateGateway(t *testing.T) { }, { desc: "tls config not set with https protocol", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("https"), - Protocol: gatewayv1b1.HTTPSProtocolType, - Port: gatewayv1b1.PortNumber(8443), + Name: gatewayv1.SectionName("https"), + Protocol: gatewayv1.HTTPSProtocolType, + Port: gatewayv1.PortNumber(8443), }, } }, @@ -96,12 +96,12 @@ func TestValidateGateway(t *testing.T) { }, { desc: "tls config not set with tls protocol", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("tls"), - Protocol: gatewayv1b1.TLSProtocolType, - Port: gatewayv1b1.PortNumber(8443), + Name: gatewayv1.SectionName("tls"), + Protocol: gatewayv1.TLSProtocolType, + Port: gatewayv1.PortNumber(8443), }, } }, @@ -109,49 +109,49 @@ func TestValidateGateway(t *testing.T) { }, { desc: "tls config not set with http protocol", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("http"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(8080), + Name: gatewayv1.SectionName("http"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(8080), }, } }, }, { desc: "tls config not set with tcp protocol", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("tcp"), - Protocol: gatewayv1b1.TCPProtocolType, - Port: gatewayv1b1.PortNumber(8080), + Name: gatewayv1.SectionName("tcp"), + Protocol: gatewayv1.TCPProtocolType, + Port: gatewayv1.PortNumber(8080), }, } }, }, { desc: "tls config not set with udp protocol", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("udp"), - Protocol: gatewayv1b1.UDPProtocolType, - Port: gatewayv1b1.PortNumber(8080), + Name: gatewayv1.SectionName("udp"), + Protocol: gatewayv1.UDPProtocolType, + Port: gatewayv1.PortNumber(8080), }, } }, }, { desc: "hostname present with tcp protocol", - mutate: func(gw *gatewayv1b1.Gateway) { - hostname := gatewayv1b1.Hostname("foo") - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + hostname := gatewayv1.Hostname("foo") + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("tcp"), - Protocol: gatewayv1b1.TCPProtocolType, - Port: gatewayv1b1.PortNumber(8080), + Name: gatewayv1.SectionName("tcp"), + Protocol: gatewayv1.TCPProtocolType, + Port: gatewayv1.PortNumber(8080), Hostname: &hostname, }, } @@ -160,13 +160,13 @@ func TestValidateGateway(t *testing.T) { }, { desc: "hostname present with udp protocol", - mutate: func(gw *gatewayv1b1.Gateway) { - hostname := gatewayv1b1.Hostname("foo") - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + hostname := gatewayv1.Hostname("foo") + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("udp"), - Protocol: gatewayv1b1.UDPProtocolType, - Port: gatewayv1b1.PortNumber(8080), + Name: gatewayv1.SectionName("udp"), + Protocol: gatewayv1.UDPProtocolType, + Port: gatewayv1.PortNumber(8080), Hostname: &hostname, }, } @@ -175,14 +175,14 @@ func TestValidateGateway(t *testing.T) { }, { desc: "certificateRefs not set with https protocol and TLS terminate mode", - mutate: func(gw *gatewayv1b1.Gateway) { - tlsMode := gatewayv1b1.TLSModeType("Terminate") - gw.Spec.Listeners = []gatewayv1b1.Listener{ - { - Name: gatewayv1b1.SectionName("https"), - Protocol: gatewayv1b1.HTTPSProtocolType, - Port: gatewayv1b1.PortNumber(8443), - TLS: &gatewayv1b1.GatewayTLSConfig{ + mutate: func(gw *gatewayv1.Gateway) { + tlsMode := gatewayv1.TLSModeType("Terminate") + gw.Spec.Listeners = []gatewayv1.Listener{ + { + Name: gatewayv1.SectionName("https"), + Protocol: gatewayv1.HTTPSProtocolType, + Port: gatewayv1.PortNumber(8443), + TLS: &gatewayv1.GatewayTLSConfig{ Mode: &tlsMode, }, }, @@ -192,14 +192,14 @@ func TestValidateGateway(t *testing.T) { }, { desc: "certificateRefs not set with tls protocol and TLS terminate mode", - mutate: func(gw *gatewayv1b1.Gateway) { - tlsMode := gatewayv1b1.TLSModeType("Terminate") - gw.Spec.Listeners = []gatewayv1b1.Listener{ - { - Name: gatewayv1b1.SectionName("tls"), - Protocol: gatewayv1b1.TLSProtocolType, - Port: gatewayv1b1.PortNumber(8443), - TLS: &gatewayv1b1.GatewayTLSConfig{ + mutate: func(gw *gatewayv1.Gateway) { + tlsMode := gatewayv1.TLSModeType("Terminate") + gw.Spec.Listeners = []gatewayv1.Listener{ + { + Name: gatewayv1.SectionName("tls"), + Protocol: gatewayv1.TLSProtocolType, + Port: gatewayv1.PortNumber(8443), + TLS: &gatewayv1.GatewayTLSConfig{ Mode: &tlsMode, }, }, @@ -209,17 +209,17 @@ func TestValidateGateway(t *testing.T) { }, { desc: "certificateRefs set with tls protocol and TLS terminate mode", - mutate: func(gw *gatewayv1b1.Gateway) { - tlsMode := gatewayv1b1.TLSModeType("Terminate") - gw.Spec.Listeners = []gatewayv1b1.Listener{ - { - Name: gatewayv1b1.SectionName("tls"), - Protocol: gatewayv1b1.TLSProtocolType, - Port: gatewayv1b1.PortNumber(8443), - TLS: &gatewayv1b1.GatewayTLSConfig{ + mutate: func(gw *gatewayv1.Gateway) { + tlsMode := gatewayv1.TLSModeType("Terminate") + gw.Spec.Listeners = []gatewayv1.Listener{ + { + Name: gatewayv1.SectionName("tls"), + Protocol: gatewayv1.TLSProtocolType, + Port: gatewayv1.PortNumber(8443), + TLS: &gatewayv1.GatewayTLSConfig{ Mode: &tlsMode, - CertificateRefs: []gatewayv1b1.SecretObjectReference{ - {Name: gatewayv1b1.ObjectName("foo")}, + CertificateRefs: []gatewayv1.SecretObjectReference{ + {Name: gatewayv1.ObjectName("foo")}, }, }, }, @@ -228,22 +228,22 @@ func TestValidateGateway(t *testing.T) { }, { desc: "names are not unique within the Gateway", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("http"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(80), + Name: gatewayv1.SectionName("http"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(80), }, { - Name: gatewayv1b1.SectionName("http"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(8000), + Name: gatewayv1.SectionName("http"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(8000), }, { - Name: gatewayv1b1.SectionName("http"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(8080), + Name: gatewayv1.SectionName("http"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(8080), }, } }, @@ -251,41 +251,41 @@ func TestValidateGateway(t *testing.T) { }, { desc: "names are unique within the Gateway", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("http-1"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(80), + Name: gatewayv1.SectionName("http-1"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(80), }, { - Name: gatewayv1b1.SectionName("http-2"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(8000), + Name: gatewayv1.SectionName("http-2"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(8000), }, { - Name: gatewayv1b1.SectionName("http-3"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(8080), + Name: gatewayv1.SectionName("http-3"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(8080), }, } }, }, { desc: "combination of port, protocol, and hostname are not unique for each listener", - mutate: func(gw *gatewayv1b1.Gateway) { - hostnameFoo := gatewayv1b1.Hostname("foo.com") - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + hostnameFoo := gatewayv1.Hostname("foo.com") + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("foo"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(80), + Name: gatewayv1.SectionName("foo"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(80), Hostname: &hostnameFoo, }, { - Name: gatewayv1b1.SectionName("bar"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(80), + Name: gatewayv1.SectionName("bar"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(80), Hostname: &hostnameFoo, }, } @@ -294,17 +294,17 @@ func TestValidateGateway(t *testing.T) { }, { desc: "combination of port and protocol are not unique for each listener when hostnames not set", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("foo"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(80), + Name: gatewayv1.SectionName("foo"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(80), }, { - Name: gatewayv1b1.SectionName("bar"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(80), + Name: gatewayv1.SectionName("bar"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(80), }, } }, @@ -312,19 +312,19 @@ func TestValidateGateway(t *testing.T) { }, { desc: "port is unique when protocol and hostname are the same", - mutate: func(gw *gatewayv1b1.Gateway) { - hostnameFoo := gatewayv1b1.Hostname("foo.com") - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + hostnameFoo := gatewayv1.Hostname("foo.com") + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("foo"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(80), + Name: gatewayv1.SectionName("foo"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(80), Hostname: &hostnameFoo, }, { - Name: gatewayv1b1.SectionName("bar"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(8000), + Name: gatewayv1.SectionName("bar"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(8000), Hostname: &hostnameFoo, }, } @@ -332,20 +332,20 @@ func TestValidateGateway(t *testing.T) { }, { desc: "hostname is unique when protocol and port are the same", - mutate: func(gw *gatewayv1b1.Gateway) { - hostnameFoo := gatewayv1b1.Hostname("foo.com") - hostnameBar := gatewayv1b1.Hostname("bar.com") - gw.Spec.Listeners = []gatewayv1b1.Listener{ - { - Name: gatewayv1b1.SectionName("foo"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(80), + mutate: func(gw *gatewayv1.Gateway) { + hostnameFoo := gatewayv1.Hostname("foo.com") + hostnameBar := gatewayv1.Hostname("bar.com") + gw.Spec.Listeners = []gatewayv1.Listener{ + { + Name: gatewayv1.SectionName("foo"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(80), Hostname: &hostnameFoo, }, { - Name: gatewayv1b1.SectionName("bar"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(80), + Name: gatewayv1.SectionName("bar"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(80), Hostname: &hostnameBar, }, } @@ -353,42 +353,42 @@ func TestValidateGateway(t *testing.T) { }, { desc: "one omitted hostname is unique when protocol and port are the same", - mutate: func(gw *gatewayv1b1.Gateway) { - hostnameFoo := gatewayv1b1.Hostname("foo.com") - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + hostnameFoo := gatewayv1.Hostname("foo.com") + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("foo"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(80), + Name: gatewayv1.SectionName("foo"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(80), Hostname: &hostnameFoo, }, { - Name: gatewayv1b1.SectionName("bar"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(80), + Name: gatewayv1.SectionName("bar"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(80), }, } }, }, { desc: "protocol is unique when port and hostname are the same", - mutate: func(gw *gatewayv1b1.Gateway) { - hostnameFoo := gatewayv1b1.Hostname("foo.com") - gw.Spec.Listeners = []gatewayv1b1.Listener{ + mutate: func(gw *gatewayv1.Gateway) { + hostnameFoo := gatewayv1.Hostname("foo.com") + gw.Spec.Listeners = []gatewayv1.Listener{ { - Name: gatewayv1b1.SectionName("foo"), - Protocol: gatewayv1b1.HTTPProtocolType, - Port: gatewayv1b1.PortNumber(8000), + Name: gatewayv1.SectionName("foo"), + Protocol: gatewayv1.HTTPProtocolType, + Port: gatewayv1.PortNumber(8000), Hostname: &hostnameFoo, }, { - Name: gatewayv1b1.SectionName("bar"), - Protocol: gatewayv1b1.HTTPSProtocolType, - Port: gatewayv1b1.PortNumber(8000), + Name: gatewayv1.SectionName("bar"), + Protocol: gatewayv1.HTTPSProtocolType, + Port: gatewayv1.PortNumber(8000), Hostname: &hostnameFoo, - TLS: &gatewayv1b1.GatewayTLSConfig{ - CertificateRefs: []gatewayv1b1.SecretObjectReference{ - {Name: gatewayv1b1.ObjectName("foo")}, + TLS: &gatewayv1.GatewayTLSConfig{ + CertificateRefs: []gatewayv1.SecretObjectReference{ + {Name: gatewayv1.ObjectName("foo")}, }, }, }, @@ -397,18 +397,18 @@ func TestValidateGateway(t *testing.T) { }, { desc: "ip address and hostname in addresses are valid", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Addresses = []gatewayv1b1.GatewayAddress{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Addresses = []gatewayv1.GatewayAddress{ { - Type: ptrTo(gatewayv1b1.IPAddressType), + Type: ptrTo(gatewayv1.IPAddressType), Value: "1.2.3.4", }, { - Type: ptrTo(gatewayv1b1.IPAddressType), + Type: ptrTo(gatewayv1.IPAddressType), Value: "1111:2222:3333:4444::", }, { - Type: ptrTo(gatewayv1b1.HostnameAddressType), + Type: ptrTo(gatewayv1.HostnameAddressType), Value: "foo.bar", }, } @@ -416,18 +416,18 @@ func TestValidateGateway(t *testing.T) { }, { desc: "ip address and hostname in addresses are invalid", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Addresses = []gatewayv1b1.GatewayAddress{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Addresses = []gatewayv1.GatewayAddress{ { - Type: ptrTo(gatewayv1b1.IPAddressType), + Type: ptrTo(gatewayv1.IPAddressType), Value: "1.2.3.4:8080", }, { - Type: ptrTo(gatewayv1b1.HostnameAddressType), + Type: ptrTo(gatewayv1.HostnameAddressType), Value: "*foo/bar", }, { - Type: ptrTo(gatewayv1b1.HostnameAddressType), + Type: ptrTo(gatewayv1.HostnameAddressType), Value: "12:34:56::", }, } @@ -436,18 +436,18 @@ func TestValidateGateway(t *testing.T) { }, { desc: "ip address and hostname in status addresses are valid", - mutateStatus: func(gw *gatewayv1b1.Gateway) { - gw.Status.Addresses = []gatewayv1b1.GatewayStatusAddress{ + mutateStatus: func(gw *gatewayv1.Gateway) { + gw.Status.Addresses = []gatewayv1.GatewayStatusAddress{ { - Type: ptrTo(gatewayv1b1.IPAddressType), + Type: ptrTo(gatewayv1.IPAddressType), Value: "1.2.3.4", }, { - Type: ptrTo(gatewayv1b1.IPAddressType), + Type: ptrTo(gatewayv1.IPAddressType), Value: "1111:2222:3333:4444::", }, { - Type: ptrTo(gatewayv1b1.HostnameAddressType), + Type: ptrTo(gatewayv1.HostnameAddressType), Value: "foo.bar", }, } @@ -455,18 +455,18 @@ func TestValidateGateway(t *testing.T) { }, { desc: "ip address and hostname in status addresses are invalid", - mutateStatus: func(gw *gatewayv1b1.Gateway) { - gw.Status.Addresses = []gatewayv1b1.GatewayStatusAddress{ + mutateStatus: func(gw *gatewayv1.Gateway) { + gw.Status.Addresses = []gatewayv1.GatewayStatusAddress{ { - Type: ptrTo(gatewayv1b1.IPAddressType), + Type: ptrTo(gatewayv1.IPAddressType), Value: "1.2.3.4:8080", }, { - Type: ptrTo(gatewayv1b1.HostnameAddressType), + Type: ptrTo(gatewayv1.HostnameAddressType), Value: "*foo/bar", }, { - Type: ptrTo(gatewayv1b1.HostnameAddressType), + Type: ptrTo(gatewayv1.HostnameAddressType), Value: "12:34:56::", }, } @@ -475,22 +475,22 @@ func TestValidateGateway(t *testing.T) { }, { desc: "duplicate ip address or hostname", - mutate: func(gw *gatewayv1b1.Gateway) { - gw.Spec.Addresses = []gatewayv1b1.GatewayAddress{ + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Addresses = []gatewayv1.GatewayAddress{ { - Type: ptrTo(gatewayv1b1.IPAddressType), + Type: ptrTo(gatewayv1.IPAddressType), Value: "1.2.3.4", }, { - Type: ptrTo(gatewayv1b1.IPAddressType), + Type: ptrTo(gatewayv1.IPAddressType), Value: "1.2.3.4", }, { - Type: ptrTo(gatewayv1b1.HostnameAddressType), + Type: ptrTo(gatewayv1.HostnameAddressType), Value: "foo.bar", }, { - Type: ptrTo(gatewayv1b1.HostnameAddressType), + Type: ptrTo(gatewayv1.HostnameAddressType), Value: "foo.bar", }, } diff --git a/pkg/test/cel/gatewayclass_test.go b/pkg/test/cel/gatewayclass_test.go index 90d9c7de93..8c8225906e 100644 --- a/pkg/test/cel/gatewayclass_test.go +++ b/pkg/test/cel/gatewayclass_test.go @@ -23,34 +23,34 @@ import ( "testing" "time" - gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestValidateGatewayClassUpdate(t *testing.T) { ctx := context.Background() - baseGatewayClass := gatewayv1b1.GatewayClass{ + baseGatewayClass := gatewayv1.GatewayClass{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", }, - Spec: gatewayv1b1.GatewayClassSpec{ + Spec: gatewayv1.GatewayClassSpec{ ControllerName: "example.net/gateway-controller", }, } testCases := []struct { desc string - creationMutate func(gw *gatewayv1b1.GatewayClass) - updationMutate func(gw *gatewayv1b1.GatewayClass) + creationMutate func(gw *gatewayv1.GatewayClass) + updationMutate func(gw *gatewayv1.GatewayClass) wantError string }{ { desc: "cannot upgrade controllerName", - creationMutate: func(gwc *gatewayv1b1.GatewayClass) { + creationMutate: func(gwc *gatewayv1.GatewayClass) { gwc.Spec.ControllerName = "example.net/gateway-controller-1" }, - updationMutate: func(gwc *gatewayv1b1.GatewayClass) { + updationMutate: func(gwc *gatewayv1.GatewayClass) { gwc.Spec.ControllerName = "example.net/gateway-controller-2" }, wantError: "Value is immutable", diff --git a/pkg/test/cel/httproute_experimental_test.go b/pkg/test/cel/httproute_experimental_test.go index 69076e0ada..0e9c3c4cee 100644 --- a/pkg/test/cel/httproute_experimental_test.go +++ b/pkg/test/cel/httproute_experimental_test.go @@ -24,7 +24,7 @@ import ( "testing" "time" - gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -48,126 +48,126 @@ func TestHTTPRouteParentRefExperimental(t *testing.T) { tests := []struct { name string wantErrors []string - parentRefs []gatewayv1b1.ParentReference + parentRefs []gatewayv1.ParentReference }{ { name: "invalid because duplicate parent refs without port or section name", wantErrors: []string{"sectionName or port must be unique when parentRefs includes 2 or more references to the same parent"}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }}, }, { name: "invalid because duplicate parent refs with only one port", wantErrors: []string{"sectionName or port must be specified when parentRefs includes 2 or more references to the same parent"}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }}, }, { name: "invalid because duplicate parent refs with only one sectionName and port", wantErrors: []string{"sectionName or port must be specified when parentRefs includes 2 or more references to the same parent"}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), - Port: ptrTo(gatewayv1b1.PortNumber(80)), + SectionName: ptrTo(gatewayv1.SectionName("foo")), + Port: ptrTo(gatewayv1.PortNumber(80)), }}, }, { name: "invalid because duplicate parent refs with duplicate ports", wantErrors: []string{"sectionName or port must be unique when parentRefs includes 2 or more references to the same parent"}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }}, }, { name: "valid single parentRef without sectionName or port", wantErrors: []string{}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }}, }, { name: "valid single parentRef with sectionName and port", wantErrors: []string{}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), - Port: ptrTo(gatewayv1b1.PortNumber(443)), + SectionName: ptrTo(gatewayv1.SectionName("foo")), + Port: ptrTo(gatewayv1.PortNumber(443)), }}, }, { name: "valid because duplicate parent refs with different ports", wantErrors: []string{}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - Port: ptrTo(gatewayv1b1.PortNumber(443)), + Port: ptrTo(gatewayv1.PortNumber(443)), }}, }, { name: "invalid ParentRefs with multiple mixed references to the same parent", wantErrors: []string{"sectionName or port must be specified when parentRefs includes 2 or more references to the same parent"}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - Port: ptrTo(gatewayv1b1.PortNumber(443)), + Port: ptrTo(gatewayv1.PortNumber(443)), }}, }, { name: "valid ParentRefs with multiple same port references to different section of a parent", wantErrors: []string{}, - parentRefs: []gatewayv1b1.ParentReference{{ + parentRefs: []gatewayv1.ParentReference{{ Name: "example", - Port: ptrTo(gatewayv1b1.PortNumber(443)), - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), + Port: ptrTo(gatewayv1.PortNumber(443)), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }, { Name: "example", - Port: ptrTo(gatewayv1b1.PortNumber(443)), - SectionName: ptrTo(gatewayv1b1.SectionName("bar")), + Port: ptrTo(gatewayv1.PortNumber(443)), + SectionName: ptrTo(gatewayv1.SectionName("bar")), }}, }, { @@ -176,58 +176,58 @@ func TestHTTPRouteParentRefExperimental(t *testing.T) { // sectionName, or both) name: "invalid because duplicate parent refs with first having sectionName and second having both sectionName and port", wantErrors: []string{"sectionName or port must be specified when parentRefs includes 2 or more references to the same parent"}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - Port: ptrTo(gatewayv1b1.PortNumber(443)), - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), + Port: ptrTo(gatewayv1.PortNumber(443)), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }}, }, { name: "valid because first parentRef has namespace while second doesn't", wantErrors: []string{}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - Namespace: ptrTo(gatewayv1b1.Namespace("test")), + Namespace: ptrTo(gatewayv1.Namespace("test")), }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }}, }, { name: "valid because second parentRef has namespace while first doesn't", wantErrors: []string{}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - Namespace: ptrTo(gatewayv1b1.Namespace("test")), + Namespace: ptrTo(gatewayv1.Namespace("test")), }}, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - route := &gatewayv1b1.HTTPRoute{ + route := &gatewayv1.HTTPRoute{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), Namespace: metav1.NamespaceDefault, }, - Spec: gatewayv1b1.HTTPRouteSpec{ - CommonRouteSpec: gatewayv1b1.CommonRouteSpec{ + Spec: gatewayv1.HTTPRouteSpec{ + CommonRouteSpec: gatewayv1.CommonRouteSpec{ ParentRefs: tc.parentRefs, }, }, @@ -237,22 +237,22 @@ func TestHTTPRouteParentRefExperimental(t *testing.T) { } } -func toDuration(durationString string) *gatewayv1b1.Duration { - return (*gatewayv1b1.Duration)(&durationString) +func toDuration(durationString string) *gatewayv1.Duration { + return (*gatewayv1.Duration)(&durationString) } func TestHTTPRouteTimeouts(t *testing.T) { tests := []struct { name string wantErrors []string - rules []gatewayv1b1.HTTPRouteRule + rules []gatewayv1.HTTPRouteRule }{ { name: "invalid timeout unit us is not supported", wantErrors: []string{"Invalid value: \"100us\": spec.rules[0].timeouts.request in body should match '^([0-9]{1,5}(h|m|s|ms)){1,4}$'"}, - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Timeouts: &gatewayv1b1.HTTPRouteTimeouts{ + Timeouts: &gatewayv1.HTTPRouteTimeouts{ Request: toDuration("100us"), }, }, @@ -261,9 +261,9 @@ func TestHTTPRouteTimeouts(t *testing.T) { { name: "invalid timeout unit ns is not supported", wantErrors: []string{"Invalid value: \"500ns\": spec.rules[0].timeouts.request in body should match '^([0-9]{1,5}(h|m|s|ms)){1,4}$'"}, - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Timeouts: &gatewayv1b1.HTTPRouteTimeouts{ + Timeouts: &gatewayv1.HTTPRouteTimeouts{ Request: toDuration("500ns"), }, }, @@ -271,9 +271,9 @@ func TestHTTPRouteTimeouts(t *testing.T) { }, { name: "valid timeout request and backendRequest", - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Timeouts: &gatewayv1b1.HTTPRouteTimeouts{ + Timeouts: &gatewayv1.HTTPRouteTimeouts{ Request: toDuration("4s"), BackendRequest: toDuration("2s"), }, @@ -282,9 +282,9 @@ func TestHTTPRouteTimeouts(t *testing.T) { }, { name: "valid timeout request", - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Timeouts: &gatewayv1b1.HTTPRouteTimeouts{ + Timeouts: &gatewayv1.HTTPRouteTimeouts{ Request: toDuration("0s"), }, }, @@ -293,9 +293,9 @@ func TestHTTPRouteTimeouts(t *testing.T) { { name: "invalid timeout request day unit not supported", wantErrors: []string{"Invalid value: \"1d\": spec.rules[0].timeouts.request in body should match '^([0-9]{1,5}(h|m|s|ms)){1,4}$'"}, - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Timeouts: &gatewayv1b1.HTTPRouteTimeouts{ + Timeouts: &gatewayv1.HTTPRouteTimeouts{ Request: toDuration("1d"), }, }, @@ -304,9 +304,9 @@ func TestHTTPRouteTimeouts(t *testing.T) { { name: "invalid timeout request decimal not supported ", wantErrors: []string{"Invalid value: \"0.5s\": spec.rules[0].timeouts.request in body should match '^([0-9]{1,5}(h|m|s|ms)){1,4}$'"}, - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Timeouts: &gatewayv1b1.HTTPRouteTimeouts{ + Timeouts: &gatewayv1.HTTPRouteTimeouts{ Request: toDuration("0.5s"), }, }, @@ -314,9 +314,9 @@ func TestHTTPRouteTimeouts(t *testing.T) { }, { name: "valid timeout request infinite greater than backendRequest 1ms", - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Timeouts: &gatewayv1b1.HTTPRouteTimeouts{ + Timeouts: &gatewayv1.HTTPRouteTimeouts{ Request: toDuration("0s"), BackendRequest: toDuration("1ms"), }, @@ -325,9 +325,9 @@ func TestHTTPRouteTimeouts(t *testing.T) { }, { name: "valid timeout request 1s greater than backendRequest 200ms", - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Timeouts: &gatewayv1b1.HTTPRouteTimeouts{ + Timeouts: &gatewayv1.HTTPRouteTimeouts{ Request: toDuration("1s"), BackendRequest: toDuration("200ms"), }, @@ -336,9 +336,9 @@ func TestHTTPRouteTimeouts(t *testing.T) { }, { name: "valid timeout request 10s equal backendRequest 10s", - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Timeouts: &gatewayv1b1.HTTPRouteTimeouts{ + Timeouts: &gatewayv1.HTTPRouteTimeouts{ Request: toDuration("10s"), BackendRequest: toDuration("10s"), }, @@ -348,9 +348,9 @@ func TestHTTPRouteTimeouts(t *testing.T) { { name: "invalid timeout request 200ms less than backendRequest 1s", wantErrors: []string{"Invalid value: \"object\": backendRequest timeout cannot be longer than request timeout"}, - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Timeouts: &gatewayv1b1.HTTPRouteTimeouts{ + Timeouts: &gatewayv1.HTTPRouteTimeouts{ Request: toDuration("200ms"), BackendRequest: toDuration("1s"), }, @@ -361,12 +361,12 @@ func TestHTTPRouteTimeouts(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - route := &gatewayv1b1.HTTPRoute{ + route := &gatewayv1.HTTPRoute{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), Namespace: metav1.NamespaceDefault, }, - Spec: gatewayv1b1.HTTPRouteSpec{Rules: tc.rules}, + Spec: gatewayv1.HTTPRouteSpec{Rules: tc.rules}, } validateHTTPRoute(t, route, tc.wantErrors) }) diff --git a/pkg/test/cel/httproute_standard_test.go b/pkg/test/cel/httproute_standard_test.go index 535009fec6..af470cfe88 100644 --- a/pkg/test/cel/httproute_standard_test.go +++ b/pkg/test/cel/httproute_standard_test.go @@ -24,7 +24,7 @@ import ( "testing" "time" - gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -48,138 +48,138 @@ func TestHTTPRouteParentRefStandard(t *testing.T) { tests := []struct { name string wantErrors []string - parentRefs []gatewayv1b1.ParentReference + parentRefs []gatewayv1.ParentReference }{ { name: "invalid because duplicate parent refs without section name", wantErrors: []string{"sectionName must be unique when parentRefs includes 2 or more references to the same parent"}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }}, }, { name: "invalid because duplicate parent refs with only one section name", wantErrors: []string{"sectionName must be specified when parentRefs includes 2 or more references to the same parent"}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }}, }, { name: "invalid because duplicate parent refs with duplicate section names", wantErrors: []string{"sectionName must be unique when parentRefs includes 2 or more references to the same parent"}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }}, }, { name: "valid single parentRef without sectionName", wantErrors: []string{}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }}, }, { name: "valid single parentRef with sectionName", wantErrors: []string{}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }}, }, { name: "valid because duplicate parent refs with different section names", wantErrors: []string{}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - SectionName: ptrTo(gatewayv1b1.SectionName("bar")), + SectionName: ptrTo(gatewayv1.SectionName("bar")), }}, }, { name: "valid because duplicate parent refs with different names", wantErrors: []string{}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example2", - SectionName: ptrTo(gatewayv1b1.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }}, }, { name: "valid because first parentRef has namespace while second doesn't", wantErrors: []string{}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - Namespace: ptrTo(gatewayv1b1.Namespace("test")), + Namespace: ptrTo(gatewayv1.Namespace("test")), }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }}, }, { name: "valid because second parentRef has namespace while first doesn't", wantErrors: []string{}, - parentRefs: []gatewayv1b1.ParentReference{{ - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + parentRefs: []gatewayv1.ParentReference{{ + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", }, { - Kind: ptrTo(gatewayv1b1.Kind("Gateway")), - Group: ptrTo(gatewayv1b1.Group("gateway.networking.k8s.io")), + Kind: ptrTo(gatewayv1.Kind("Gateway")), + Group: ptrTo(gatewayv1.Group("gateway.networking.k8s.io")), Name: "example", - Namespace: ptrTo(gatewayv1b1.Namespace("test")), + Namespace: ptrTo(gatewayv1.Namespace("test")), }}, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - route := &gatewayv1b1.HTTPRoute{ + route := &gatewayv1.HTTPRoute{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), Namespace: metav1.NamespaceDefault, }, - Spec: gatewayv1b1.HTTPRouteSpec{ - CommonRouteSpec: gatewayv1b1.CommonRouteSpec{ + Spec: gatewayv1.HTTPRouteSpec{ + CommonRouteSpec: gatewayv1.CommonRouteSpec{ ParentRefs: tc.parentRefs, }, }, diff --git a/pkg/test/cel/httproute_test.go b/pkg/test/cel/httproute_test.go index f80e004c1e..0ef2f88107 100644 --- a/pkg/test/cel/httproute_test.go +++ b/pkg/test/cel/httproute_test.go @@ -23,7 +23,7 @@ import ( "testing" "time" - gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -47,73 +47,73 @@ func TestHTTPPathMatch(t *testing.T) { tests := []struct { name string wantErrors []string - path *gatewayv1b1.HTTPPathMatch + path *gatewayv1.HTTPPathMatch }{ { name: "invalid because path does not start with '/'", wantErrors: []string{"value must be an absolute path and start with '/' when type one of ['Exact', 'PathPrefix']"}, - path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("foo"), }, }, { name: "invalid httpRoute prefix (/.)", wantErrors: []string{"must not end with '/.' when type one of ['Exact', 'PathPrefix']"}, - path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/."), }, }, { name: "invalid exact (/./)", wantErrors: []string{"must not contain '/./' when type one of ['Exact', 'PathPrefix']"}, - path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("Exact")), + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("Exact")), Value: ptrTo("/foo/./bar"), }, }, { name: "invalid type", wantErrors: []string{"type must be one of ['Exact', 'PathPrefix', 'RegularExpression']"}, - path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("FooBar")), + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("FooBar")), Value: ptrTo("/path"), }, }, { name: "valid because type is RegularExpression but would not be valid for Exact", - path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("RegularExpression")), + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("RegularExpression")), Value: ptrTo("/foo/./bar"), }, }, { name: "valid httpRoute prefix", - path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/path"), }, }, { name: "valid path with some special characters", - path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("Exact")), + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("Exact")), Value: ptrTo("/abc/123'/a-b-c/d@gmail/%0A"), }, }, { name: "invalid prefix path (/[])", - path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/[]"), }, wantErrors: []string{"must only contain valid characters (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) for types ['Exact', 'PathPrefix']"}, }, { name: "invalid exact path (/^)", - path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("Exact")), + path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("Exact")), Value: ptrTo("/^"), }, wantErrors: []string{"must only contain valid characters (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) for types ['Exact', 'PathPrefix']"}, @@ -122,21 +122,21 @@ func TestHTTPPathMatch(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - route := &gatewayv1b1.HTTPRoute{ + route := &gatewayv1.HTTPRoute{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), Namespace: metav1.NamespaceDefault, }, - Spec: gatewayv1b1.HTTPRouteSpec{ - Rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{{ + Spec: gatewayv1.HTTPRouteSpec{ + Rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{{ Path: tc.path, }}, - BackendRefs: []gatewayv1b1.HTTPBackendRef{{ - BackendRef: gatewayv1b1.BackendRef{ - BackendObjectReference: gatewayv1b1.BackendObjectReference{ - Name: gatewayv1b1.ObjectName("test"), - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + BackendRefs: []gatewayv1.HTTPBackendRef{{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: gatewayv1.ObjectName("test"), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, }}, @@ -149,30 +149,30 @@ func TestHTTPPathMatch(t *testing.T) { } func TestBackendObjectReference(t *testing.T) { - portPtr := func(n int) *gatewayv1b1.PortNumber { - p := gatewayv1b1.PortNumber(n) + portPtr := func(n int) *gatewayv1.PortNumber { + p := gatewayv1.PortNumber(n) return &p } - groupPtr := func(g string) *gatewayv1b1.Group { - p := gatewayv1b1.Group(g) + groupPtr := func(g string) *gatewayv1.Group { + p := gatewayv1.Group(g) return &p } - kindPtr := func(k string) *gatewayv1b1.Kind { - p := gatewayv1b1.Kind(k) + kindPtr := func(k string) *gatewayv1.Kind { + p := gatewayv1.Kind(k) return &p } tests := []struct { name string wantErrors []string - rules []gatewayv1b1.HTTPRouteRule - backendRef gatewayv1b1.BackendObjectReference + rules []gatewayv1.HTTPRouteRule + backendRef gatewayv1.BackendObjectReference }{ { name: "default groupkind with port", - backendRef: gatewayv1b1.BackendObjectReference{ + backendRef: gatewayv1.BackendObjectReference{ Name: "backend", Port: portPtr(99), }, @@ -180,13 +180,13 @@ func TestBackendObjectReference(t *testing.T) { { name: "default groupkind with no port", wantErrors: []string{"Must have port for Service reference"}, - backendRef: gatewayv1b1.BackendObjectReference{ + backendRef: gatewayv1.BackendObjectReference{ Name: "backend", }, }, { name: "explicit service with port", - backendRef: gatewayv1b1.BackendObjectReference{ + backendRef: gatewayv1.BackendObjectReference{ Group: groupPtr(""), Kind: kindPtr("Service"), Name: "backend", @@ -196,7 +196,7 @@ func TestBackendObjectReference(t *testing.T) { { name: "explicit service with no port", wantErrors: []string{"Must have port for Service reference"}, - backendRef: gatewayv1b1.BackendObjectReference{ + backendRef: gatewayv1.BackendObjectReference{ Group: groupPtr(""), Kind: kindPtr("Service"), Name: "backend", @@ -204,7 +204,7 @@ func TestBackendObjectReference(t *testing.T) { }, { name: "explicit ref with no port", - backendRef: gatewayv1b1.BackendObjectReference{ + backendRef: gatewayv1.BackendObjectReference{ Group: groupPtr("foo.example.com"), Kind: kindPtr("Foo"), Name: "backend", @@ -214,15 +214,15 @@ func TestBackendObjectReference(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - route := &gatewayv1b1.HTTPRoute{ + route := &gatewayv1.HTTPRoute{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), Namespace: metav1.NamespaceDefault, }, - Spec: gatewayv1b1.HTTPRouteSpec{ - Rules: []gatewayv1b1.HTTPRouteRule{{ - BackendRefs: []gatewayv1b1.HTTPBackendRef{{ - BackendRef: gatewayv1b1.BackendRef{ + Spec: gatewayv1.HTTPRouteSpec{ + Rules: []gatewayv1.HTTPRouteRule{{ + BackendRefs: []gatewayv1.HTTPBackendRef{{ + BackendRef: gatewayv1.BackendRef{ BackendObjectReference: tc.backendRef, }, }}, @@ -238,98 +238,98 @@ func TestHTTPRouteFilter(t *testing.T) { tests := []struct { name string wantErrors []string - routeFilter gatewayv1b1.HTTPRouteFilter + routeFilter gatewayv1.HTTPRouteFilter }{ { name: "valid HTTPRouteFilterRequestHeaderModifier route filter", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, - RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ - Set: []gatewayv1b1.HTTPHeader{{Name: "name", Value: "foo"}}, - Add: []gatewayv1b1.HTTPHeader{{Name: "add", Value: "foo"}}, + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Set: []gatewayv1.HTTPHeader{{Name: "name", Value: "foo"}}, + Add: []gatewayv1.HTTPHeader{{Name: "add", Value: "foo"}}, Remove: []string{"remove"}, }, }, }, { name: "invalid HTTPRouteFilterRequestHeaderModifier type filter with non-matching field", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, - RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{}, + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{}, }, wantErrors: []string{"filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type", "filter.requestMirror must be nil if the filter.type is not RequestMirror"}, }, { name: "invalid HTTPRouteFilterRequestHeaderModifier type filter with empty value field", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, }, wantErrors: []string{"filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type"}, }, { name: "valid HTTPRouteFilterRequestMirror route filter", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, - RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{BackendRef: gatewayv1b1.BackendObjectReference{ - Group: ptrTo(gatewayv1b1.Group("group")), - Kind: ptrTo(gatewayv1b1.Kind("kind")), + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{BackendRef: gatewayv1.BackendObjectReference{ + Group: ptrTo(gatewayv1.Group("group")), + Kind: ptrTo(gatewayv1.Kind("kind")), Name: "name", - Namespace: ptrTo(gatewayv1b1.Namespace("ns")), - Port: ptrTo(gatewayv1b1.PortNumber(22)), + Namespace: ptrTo(gatewayv1.Namespace("ns")), + Port: ptrTo(gatewayv1.PortNumber(22)), }}, }, }, { name: "invalid HTTPRouteFilterRequestMirror type filter with non-matching field", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, - RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{}, + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{}, }, wantErrors: []string{"filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier", "filter.requestMirror must be specified for RequestMirror filter.type"}, }, { name: "invalid HTTPRouteFilterRequestMirror type filter with empty value field", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestMirror, }, wantErrors: []string{"filter.requestMirror must be specified for RequestMirror filter.type"}, }, { name: "valid HTTPRouteFilterRequestRedirect route filter", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ Scheme: ptrTo("http"), - Hostname: ptrTo(gatewayv1b1.PreciseHostname("hostname")), - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.FullPathHTTPPathModifier, + Hostname: ptrTo(gatewayv1.PreciseHostname("hostname")), + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.FullPathHTTPPathModifier, ReplaceFullPath: ptrTo("path"), }, - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), StatusCode: ptrTo(302), }, }, }, { name: "invalid HTTPRouteFilterRequestRedirect type filter with non-matching field", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{}, + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{}, }, wantErrors: []string{"filter.requestMirror must be nil if the filter.type is not RequestMirror", "filter.requestRedirect must be specified for RequestRedirect filter.type"}, }, { name: "invalid HTTPRouteFilterRequestRedirect type filter with empty value field", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, }, wantErrors: []string{"filter.requestRedirect must be specified for RequestRedirect filter.type"}, }, { name: "valid HTTPRouteFilterExtensionRef filter", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterExtensionRef, - ExtensionRef: &gatewayv1b1.LocalObjectReference{ + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterExtensionRef, + ExtensionRef: &gatewayv1.LocalObjectReference{ Group: "group", Kind: "kind", Name: "name", @@ -338,27 +338,27 @@ func TestHTTPRouteFilter(t *testing.T) { }, { name: "invalid HTTPRouteFilterExtensionRef type filter with non-matching field", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterExtensionRef, - RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{}, + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterExtensionRef, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{}, }, wantErrors: []string{"filter.requestMirror must be nil if the filter.type is not RequestMirror", "filter.extensionRef must be specified for ExtensionRef filter.type"}, }, { name: "invalid HTTPRouteFilterExtensionRef type filter with empty value field", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterExtensionRef, + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterExtensionRef, }, wantErrors: []string{"filter.extensionRef must be specified for ExtensionRef filter.type"}, }, { name: "valid HTTPRouteFilterURLRewrite route filter", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Hostname: ptrTo(gatewayv1b1.PreciseHostname("hostname")), - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.FullPathHTTPPathModifier, + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Hostname: ptrTo(gatewayv1.PreciseHostname("hostname")), + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.FullPathHTTPPathModifier, ReplaceFullPath: ptrTo("path"), }, }, @@ -366,16 +366,16 @@ func TestHTTPRouteFilter(t *testing.T) { }, { name: "invalid HTTPRouteFilterURLRewrite type filter with non-matching field", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{}, + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{}, }, wantErrors: []string{"filter.requestMirror must be nil if the filter.type is not RequestMirror", "filter.urlRewrite must be specified for URLRewrite filter.type"}, }, { name: "invalid HTTPRouteFilterURLRewrite type filter with empty value field", - routeFilter: gatewayv1b1.HTTPRouteFilter{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, + routeFilter: gatewayv1.HTTPRouteFilter{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, }, wantErrors: []string{"filter.urlRewrite must be specified for URLRewrite filter.type"}, }, @@ -383,14 +383,14 @@ func TestHTTPRouteFilter(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - route := &gatewayv1b1.HTTPRoute{ + route := &gatewayv1.HTTPRoute{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), Namespace: metav1.NamespaceDefault, }, - Spec: gatewayv1b1.HTTPRouteSpec{ - Rules: []gatewayv1b1.HTTPRouteRule{{ - Filters: []gatewayv1b1.HTTPRouteFilter{tc.routeFilter}, + Spec: gatewayv1.HTTPRouteSpec{ + Rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{tc.routeFilter}, }}, }, } @@ -400,30 +400,30 @@ func TestHTTPRouteFilter(t *testing.T) { } func TestHTTPRouteRule(t *testing.T) { - testService := gatewayv1b1.ObjectName("test-service") + testService := gatewayv1.ObjectName("test-service") tests := []struct { name string wantErrors []string - rules []gatewayv1b1.HTTPRouteRule + rules []gatewayv1.HTTPRouteRule }{ { name: "valid httpRoute with no filters", - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Matches: []gatewayv1b1.HTTPRouteMatch{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, }, - BackendRefs: []gatewayv1b1.HTTPBackendRef{ + BackendRefs: []gatewayv1.HTTPBackendRef{ { - BackendRef: gatewayv1b1.BackendRef{ - BackendObjectReference: gatewayv1b1.BackendObjectReference{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, Weight: ptrTo(int32(100)), }, @@ -434,23 +434,23 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "valid httpRoute with 1 filter", - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Matches: []gatewayv1b1.HTTPRouteMatch{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{ + Filters: []gatewayv1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, - RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{ - BackendRef: gatewayv1b1.BackendObjectReference{ + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{ + BackendRef: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(8081)), + Port: ptrTo(gatewayv1.PortNumber(8081)), }, }, }, @@ -460,21 +460,21 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "valid httpRoute with duplicate ExtensionRef filters", - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Matches: []gatewayv1b1.HTTPRouteMatch{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{ + Filters: []gatewayv1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, - RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ - Set: []gatewayv1b1.HTTPHeader{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Set: []gatewayv1.HTTPHeader{ { Name: "special-header", Value: "foo", @@ -483,31 +483,31 @@ func TestHTTPRouteRule(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, - RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{ - BackendRef: gatewayv1b1.BackendObjectReference{ + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{ + BackendRef: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, }, { Type: "ExtensionRef", - ExtensionRef: &gatewayv1b1.LocalObjectReference{ + ExtensionRef: &gatewayv1.LocalObjectReference{ Kind: "Service", Name: "test", }, }, { Type: "ExtensionRef", - ExtensionRef: &gatewayv1b1.LocalObjectReference{ + ExtensionRef: &gatewayv1.LocalObjectReference{ Kind: "Service", Name: "test", }, }, { Type: "ExtensionRef", - ExtensionRef: &gatewayv1b1.LocalObjectReference{ + ExtensionRef: &gatewayv1.LocalObjectReference{ Kind: "Service", Name: "test", }, @@ -518,14 +518,14 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "valid redirect path modifier", - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Filters: []gatewayv1b1.HTTPRouteFilter{ + Filters: []gatewayv1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.FullPathHTTPPathModifier, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.FullPathHTTPPathModifier, ReplaceFullPath: ptrTo("foo"), }, }, @@ -536,18 +536,18 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "valid rewrite path modifier", - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{{ - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{{ + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/bar"), }, }}, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -556,27 +556,27 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "multiple actions for different request headers", - rules: []gatewayv1b1.HTTPRouteRule{{ - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, - RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ - Add: []gatewayv1b1.HTTPHeader{ + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{ { - Name: gatewayv1b1.HTTPHeaderName("x-vegetable"), + Name: gatewayv1.HTTPHeaderName("x-vegetable"), Value: "carrot", }, { - Name: gatewayv1b1.HTTPHeaderName("x-grain"), + Name: gatewayv1.HTTPHeaderName("x-grain"), Value: "rye", }, }, - Set: []gatewayv1b1.HTTPHeader{ + Set: []gatewayv1.HTTPHeader{ { - Name: gatewayv1b1.HTTPHeaderName("x-fruit"), + Name: gatewayv1.HTTPHeaderName("x-fruit"), Value: "watermelon", }, { - Name: gatewayv1b1.HTTPHeaderName("x-spice"), + Name: gatewayv1.HTTPHeaderName("x-spice"), Value: "coriander", }, }, @@ -586,16 +586,16 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "multiple actions for different response headers", - rules: []gatewayv1b1.HTTPRouteRule{{ - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterResponseHeaderModifier, - ResponseHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ - Add: []gatewayv1b1.HTTPHeader{{ - Name: gatewayv1b1.HTTPHeaderName("x-example"), + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, + ResponseHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{{ + Name: gatewayv1.HTTPHeaderName("x-example"), Value: "blueberry", }}, - Set: []gatewayv1b1.HTTPHeader{{ - Name: gatewayv1b1.HTTPHeaderName("x-different"), + Set: []gatewayv1.HTTPHeader{{ + Name: gatewayv1.HTTPHeaderName("x-different"), Value: "turnip", }}, }, @@ -605,23 +605,23 @@ func TestHTTPRouteRule(t *testing.T) { { name: "backendref with request redirect httpRoute filter", wantErrors: []string{"RequestRedirect filter must not be used together with backendRefs"}, - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Filters: []gatewayv1b1.HTTPRouteFilter{ + Filters: []gatewayv1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ Scheme: ptrTo("https"), StatusCode: ptrTo(301), }, }, }, - BackendRefs: []gatewayv1b1.HTTPBackendRef{ + BackendRefs: []gatewayv1.HTTPBackendRef{ { - BackendRef: gatewayv1b1.BackendRef{ - BackendObjectReference: gatewayv1b1.BackendObjectReference{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }, }, }, @@ -631,12 +631,12 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "request redirect without backendref in httpRoute filter", - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Filters: []gatewayv1b1.HTTPRouteFilter{ + Filters: []gatewayv1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ Scheme: ptrTo("https"), StatusCode: ptrTo(301), }, @@ -647,22 +647,22 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "backendref without request redirect filter", - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Filters: []gatewayv1b1.HTTPRouteFilter{ + Filters: []gatewayv1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, - RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ - Set: []gatewayv1b1.HTTPHeader{{Name: "name", Value: "foo"}}, + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Set: []gatewayv1.HTTPHeader{{Name: "name", Value: "foo"}}, }, }, }, - BackendRefs: []gatewayv1b1.HTTPBackendRef{ + BackendRefs: []gatewayv1.HTTPBackendRef{ { - BackendRef: gatewayv1b1.BackendRef{ - BackendObjectReference: gatewayv1b1.BackendObjectReference{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }, }, }, @@ -672,14 +672,14 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "backendref without any filter", - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - BackendRefs: []gatewayv1b1.HTTPBackendRef{ + BackendRefs: []gatewayv1.HTTPBackendRef{ { - BackendRef: gatewayv1b1.BackendRef{ - BackendObjectReference: gatewayv1b1.BackendObjectReference{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }, }, }, @@ -689,20 +689,20 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "valid use of URLRewrite filter", - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{ + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/foo"), }, }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -712,26 +712,26 @@ func TestHTTPRouteRule(t *testing.T) { { name: "invalid URLRewrite filter because too many path matches", wantErrors: []string{"When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified"}, - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{ + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/foo"), }, }, { // Cannot have multiple path matches. - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/bar"), }, }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -741,20 +741,20 @@ func TestHTTPRouteRule(t *testing.T) { { name: "invalid URLRewrite filter because too many path matches", wantErrors: []string{"When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified"}, - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{ + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType(gatewayv1b1.FullPathHTTPPathModifier)), // Incorrect Patch match Type for URLRewrite filter with ReplacePrefixMatch. + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType(gatewayv1.FullPathHTTPPathModifier)), // Incorrect Patch match Type for URLRewrite filter with ReplacePrefixMatch. Value: ptrTo("/foo"), }, }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -763,20 +763,20 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "valid use of RequestRedirect filter", - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{ + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/foo"), }, }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -786,26 +786,26 @@ func TestHTTPRouteRule(t *testing.T) { { name: "invalid RequestRedirect filter because too many path matches", wantErrors: []string{"When using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified"}, - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{ + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/foo"), }, }, { // Cannot have multiple path matches. - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/bar"), }, }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -815,20 +815,20 @@ func TestHTTPRouteRule(t *testing.T) { { name: "invalid RequestRedirect filter because path match has type ReplaceFullPath", wantErrors: []string{"When using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified"}, - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{ + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType(gatewayv1b1.FullPathHTTPPathModifier)), // Incorrect Patch match Type for RequestRedirect filter with ReplacePrefixMatch. + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType(gatewayv1.FullPathHTTPPathModifier)), // Incorrect Patch match Type for RequestRedirect filter with ReplacePrefixMatch. Value: ptrTo("/foo"), }, }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -837,28 +837,28 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "valid use of URLRewrite filter (within backendRefs)", - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{ + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/foo"), }, }, }, - BackendRefs: []gatewayv1b1.HTTPBackendRef{ + BackendRefs: []gatewayv1.HTTPBackendRef{ { - BackendRef: gatewayv1b1.BackendRef{ - BackendObjectReference: gatewayv1b1.BackendObjectReference{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -870,34 +870,34 @@ func TestHTTPRouteRule(t *testing.T) { { name: "invalid URLRewrite filter (within backendRefs) because too many path matches", wantErrors: []string{"Within backendRefs, When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified"}, - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{ + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/foo"), }, }, { // Cannot have multiple path matches. - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/bar"), }, }, }, - BackendRefs: []gatewayv1b1.HTTPBackendRef{ + BackendRefs: []gatewayv1.HTTPBackendRef{ { - BackendRef: gatewayv1b1.BackendRef{ - BackendObjectReference: gatewayv1b1.BackendObjectReference{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -909,28 +909,28 @@ func TestHTTPRouteRule(t *testing.T) { { name: "invalid URLRewrite filter (within backendRefs) because path match has type ReplaceFullPath", wantErrors: []string{"Within backendRefs, When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified"}, - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{ + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType(gatewayv1b1.FullPathHTTPPathModifier)), // Incorrect Patch match Type for URLRewrite filter with ReplacePrefixMatch. + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType(gatewayv1.FullPathHTTPPathModifier)), // Incorrect Patch match Type for URLRewrite filter with ReplacePrefixMatch. Value: ptrTo("/foo"), }, }, }, - BackendRefs: []gatewayv1b1.HTTPBackendRef{ + BackendRefs: []gatewayv1.HTTPBackendRef{ { - BackendRef: gatewayv1b1.BackendRef{ - BackendObjectReference: gatewayv1b1.BackendObjectReference{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -941,28 +941,28 @@ func TestHTTPRouteRule(t *testing.T) { }, { name: "valid use of RequestRedirect filter (within backendRefs)", - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{ + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/foo"), }, }, }, - BackendRefs: []gatewayv1b1.HTTPBackendRef{ + BackendRefs: []gatewayv1.HTTPBackendRef{ { - BackendRef: gatewayv1b1.BackendRef{ - BackendObjectReference: gatewayv1b1.BackendObjectReference{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -974,34 +974,34 @@ func TestHTTPRouteRule(t *testing.T) { { name: "invalid RequestRedirect filter (within backendRefs) because too many path matches", wantErrors: []string{"Within backendRefs, when using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified"}, - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{ + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/foo"), }, }, { // Cannot have multiple path matches. - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchPathPrefix), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchPathPrefix), Value: ptrTo("/bar"), }, }, }, - BackendRefs: []gatewayv1b1.HTTPBackendRef{ + BackendRefs: []gatewayv1.HTTPBackendRef{ { - BackendRef: gatewayv1b1.BackendRef{ - BackendObjectReference: gatewayv1b1.BackendObjectReference{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -1013,28 +1013,28 @@ func TestHTTPRouteRule(t *testing.T) { { name: "invalid RequestRedirect filter (within backendRefs) because path match has type ReplaceFullPath", wantErrors: []string{"Within backendRefs, when using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified"}, - rules: []gatewayv1b1.HTTPRouteRule{{ - Matches: []gatewayv1b1.HTTPRouteMatch{ + rules: []gatewayv1.HTTPRouteRule{{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType(gatewayv1b1.FullPathHTTPPathModifier)), // Incorrect Patch match Type for RequestRedirect filter with ReplacePrefixMatch. + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType(gatewayv1.FullPathHTTPPathModifier)), // Incorrect Patch match Type for RequestRedirect filter with ReplacePrefixMatch. Value: ptrTo("/foo"), }, }, }, - BackendRefs: []gatewayv1b1.HTTPBackendRef{ + BackendRefs: []gatewayv1.HTTPBackendRef{ { - BackendRef: gatewayv1b1.BackendRef{ - BackendObjectReference: gatewayv1b1.BackendObjectReference{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -1046,20 +1046,20 @@ func TestHTTPRouteRule(t *testing.T) { { name: "rewrite and redirect filters combined (invalid)", wantErrors: []string{"May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both"}, // errCount: 3, - rules: []gatewayv1b1.HTTPRouteRule{{ - Filters: []gatewayv1b1.HTTPRouteFilter{{ - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, @@ -1069,31 +1069,31 @@ func TestHTTPRouteRule(t *testing.T) { { name: "invalid because repeated URLRewrite filter", wantErrors: []string{"URLRewrite filter cannot be repeated"}, - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Matches: []gatewayv1b1.HTTPRouteMatch{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{ + Filters: []gatewayv1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, }, { - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("bar"), }, }, @@ -1105,21 +1105,21 @@ func TestHTTPRouteRule(t *testing.T) { { name: "invalid because repeated RequestHeaderModifier filter among mix of filters", wantErrors: []string{"RequestHeaderModifier filter cannot be repeated"}, - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Matches: []gatewayv1b1.HTTPRouteMatch{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{ + Filters: []gatewayv1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, - RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ - Set: []gatewayv1b1.HTTPHeader{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Set: []gatewayv1.HTTPHeader{ { Name: "special-header", Value: "foo", @@ -1128,18 +1128,18 @@ func TestHTTPRouteRule(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestMirror, - RequestMirror: &gatewayv1b1.HTTPRequestMirrorFilter{ - BackendRef: gatewayv1b1.BackendObjectReference{ + Type: gatewayv1.HTTPRouteFilterRequestMirror, + RequestMirror: &gatewayv1.HTTPRequestMirrorFilter{ + BackendRef: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(8080)), + Port: ptrTo(gatewayv1.PortNumber(8080)), }, }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestHeaderModifier, - RequestHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ - Add: []gatewayv1b1.HTTPHeader{ + Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier, + RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{ { Name: "my-header", Value: "bar", @@ -1154,21 +1154,21 @@ func TestHTTPRouteRule(t *testing.T) { { name: "invalid because multiple filters are repeated", wantErrors: []string{"ResponseHeaderModifier filter cannot be repeated", "RequestRedirect filter cannot be repeated"}, - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Matches: []gatewayv1b1.HTTPRouteMatch{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{ + Filters: []gatewayv1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterResponseHeaderModifier, - ResponseHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ - Set: []gatewayv1b1.HTTPHeader{ + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, + ResponseHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Set: []gatewayv1.HTTPHeader{ { Name: "special-header", Value: "foo", @@ -1177,9 +1177,9 @@ func TestHTTPRouteRule(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterResponseHeaderModifier, - ResponseHeaderModifier: &gatewayv1b1.HTTPHeaderFilter{ - Add: []gatewayv1b1.HTTPHeader{ + Type: gatewayv1.HTTPRouteFilterResponseHeaderModifier, + ResponseHeaderModifier: &gatewayv1.HTTPHeaderFilter{ + Add: []gatewayv1.HTTPHeader{ { Name: "my-header", Value: "bar", @@ -1188,19 +1188,19 @@ func TestHTTPRouteRule(t *testing.T) { }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.FullPathHTTPPathModifier, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.FullPathHTTPPathModifier, ReplaceFullPath: ptrTo("foo"), }, }, }, { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.FullPathHTTPPathModifier, + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.FullPathHTTPPathModifier, ReplaceFullPath: ptrTo("bar"), }, }, @@ -1213,12 +1213,12 @@ func TestHTTPRouteRule(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - route := &gatewayv1b1.HTTPRoute{ + route := &gatewayv1.HTTPRoute{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), Namespace: metav1.NamespaceDefault, }, - Spec: gatewayv1b1.HTTPRouteSpec{Rules: tc.rules}, + Spec: gatewayv1.HTTPRouteSpec{Rules: tc.rules}, } validateHTTPRoute(t, route, tc.wantErrors) }) @@ -1226,48 +1226,48 @@ func TestHTTPRouteRule(t *testing.T) { } func TestHTTPBackendRef(t *testing.T) { - testService := gatewayv1b1.ObjectName("test-service") + testService := gatewayv1.ObjectName("test-service") tests := []struct { name string wantErrors []string - rules []gatewayv1b1.HTTPRouteRule + rules []gatewayv1.HTTPRouteRule }{ { name: "invalid because repeated URLRewrite filter within backendRefs", wantErrors: []string{"URLRewrite filter cannot be repeated"}, - rules: []gatewayv1b1.HTTPRouteRule{ + rules: []gatewayv1.HTTPRouteRule{ { - Matches: []gatewayv1b1.HTTPRouteMatch{ + Matches: []gatewayv1.HTTPRouteMatch{ { - Path: &gatewayv1b1.HTTPPathMatch{ - Type: ptrTo(gatewayv1b1.PathMatchType("PathPrefix")), + Path: &gatewayv1.HTTPPathMatch{ + Type: ptrTo(gatewayv1.PathMatchType("PathPrefix")), Value: ptrTo("/"), }, }, }, - BackendRefs: []gatewayv1b1.HTTPBackendRef{ + BackendRefs: []gatewayv1.HTTPBackendRef{ { - BackendRef: gatewayv1b1.BackendRef{ - BackendObjectReference: gatewayv1b1.BackendObjectReference{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ Name: testService, - Port: ptrTo(gatewayv1b1.PortNumber(80)), + Port: ptrTo(gatewayv1.PortNumber(80)), }, }, - Filters: []gatewayv1b1.HTTPRouteFilter{ + Filters: []gatewayv1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("foo"), }, }, }, { - Type: gatewayv1b1.HTTPRouteFilterURLRewrite, - URLRewrite: &gatewayv1b1.HTTPURLRewriteFilter{ - Path: &gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + Type: gatewayv1.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1.HTTPURLRewriteFilter{ + Path: &gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("bar"), }, }, @@ -1282,12 +1282,12 @@ func TestHTTPBackendRef(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - route := &gatewayv1b1.HTTPRoute{ + route := &gatewayv1.HTTPRoute{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), Namespace: metav1.NamespaceDefault, }, - Spec: gatewayv1b1.HTTPRouteSpec{Rules: tc.rules}, + Spec: gatewayv1.HTTPRouteSpec{Rules: tc.rules}, } validateHTTPRoute(t, route, tc.wantErrors) }) @@ -1298,47 +1298,47 @@ func TestHTTPPathModifier(t *testing.T) { tests := []struct { name string wantErrors []string - pathModifier gatewayv1b1.HTTPPathModifier + pathModifier gatewayv1.HTTPPathModifier }{ { name: "valid ReplaceFullPath", - pathModifier: gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.FullPathHTTPPathModifier, + pathModifier: gatewayv1.HTTPPathModifier{ + Type: gatewayv1.FullPathHTTPPathModifier, ReplaceFullPath: ptrTo("foo"), }, }, { name: "replaceFullPath must be specified when type is set to 'ReplaceFullPath'", wantErrors: []string{"replaceFullPath must be specified when type is set to 'ReplaceFullPath'"}, - pathModifier: gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.FullPathHTTPPathModifier, + pathModifier: gatewayv1.HTTPPathModifier{ + Type: gatewayv1.FullPathHTTPPathModifier, }, }, { name: "type must be 'ReplaceFullPath' when replaceFullPath is set", wantErrors: []string{"type must be 'ReplaceFullPath' when replaceFullPath is set"}, - pathModifier: gatewayv1b1.HTTPPathModifier{ + pathModifier: gatewayv1.HTTPPathModifier{ ReplaceFullPath: ptrTo("foo"), }, }, { name: "valid ReplacePrefixMatch", - pathModifier: gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + pathModifier: gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, ReplacePrefixMatch: ptrTo("/foo"), }, }, { name: "replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch'", wantErrors: []string{"replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch'"}, - pathModifier: gatewayv1b1.HTTPPathModifier{ - Type: gatewayv1b1.PrefixMatchHTTPPathModifier, + pathModifier: gatewayv1.HTTPPathModifier{ + Type: gatewayv1.PrefixMatchHTTPPathModifier, }, }, { name: "type must be 'ReplacePrefixMatch' when replacePrefixMatch is set", wantErrors: []string{"type must be 'ReplacePrefixMatch' when replacePrefixMatch is set"}, - pathModifier: gatewayv1b1.HTTPPathModifier{ + pathModifier: gatewayv1.HTTPPathModifier{ ReplacePrefixMatch: ptrTo("/foo"), }, }, @@ -1346,18 +1346,18 @@ func TestHTTPPathModifier(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - route := &gatewayv1b1.HTTPRoute{ + route := &gatewayv1.HTTPRoute{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), Namespace: metav1.NamespaceDefault, }, - Spec: gatewayv1b1.HTTPRouteSpec{ - Rules: []gatewayv1b1.HTTPRouteRule{ + Spec: gatewayv1.HTTPRouteSpec{ + Rules: []gatewayv1.HTTPRouteRule{ { - Filters: []gatewayv1b1.HTTPRouteFilter{ + Filters: []gatewayv1.HTTPRouteFilter{ { - Type: gatewayv1b1.HTTPRouteFilterRequestRedirect, - RequestRedirect: &gatewayv1b1.HTTPRequestRedirectFilter{ + Type: gatewayv1.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{ Path: &tc.pathModifier, }, }, @@ -1371,7 +1371,7 @@ func TestHTTPPathModifier(t *testing.T) { } } -func validateHTTPRoute(t *testing.T, route *gatewayv1b1.HTTPRoute, wantErrors []string) { +func validateHTTPRoute(t *testing.T, route *gatewayv1.HTTPRoute, wantErrors []string) { t.Helper() ctx := context.Background() diff --git a/pkg/test/cel/main_test.go b/pkg/test/cel/main_test.go index 73d3e6b4a7..655ad0d2c0 100644 --- a/pkg/test/cel/main_test.go +++ b/pkg/test/cel/main_test.go @@ -22,6 +22,7 @@ import ( "path" "testing" + v1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/apis/v1alpha2" "sigs.k8s.io/gateway-api/apis/v1beta1" @@ -48,6 +49,7 @@ func TestMain(m *testing.M) { } v1alpha2.AddToScheme(k8sClient.Scheme()) v1beta1.AddToScheme(k8sClient.Scheme()) + v1.AddToScheme(k8sClient.Scheme()) os.Exit(m.Run()) }