diff --git a/apis/v1alpha2/grpcroute_types.go b/apis/v1alpha2/grpcroute_types.go new file mode 100644 index 0000000000..03a895d084 --- /dev/null +++ b/apis/v1alpha2/grpcroute_types.go @@ -0,0 +1,461 @@ +/* +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 v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=gateway-api +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:printcolumn:name="Hostnames",type=string,JSONPath=`.spec.hostnames` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// GRPCRoute provides a way to route gRPC requests. This includes the capability +// to match requests by hostname, gRPC service, gRPC method, or HTTP/2 header. Filters can be +// used to specify additional processing steps. Backends specify where matching +// requests should be routed. +// +// Implementations supporting `GRPCRoute` with the `HTTPS` `ProtocolType` must +// accept HTTP/2 connections without an initial upgrade from HTTP/1.1. If the +// implementation does not support this, then it should raise a "Detached" +// condition for the affected listener with a reason of "UnsupportedProtocol" +// +// Implementations supporting `GRPCRoute` with the `HTTP` `ProtocolType` must +// support cleartext HTTP/2 without an initial upgrade from HTTP/1.1. If the +// implementation does not support this, then it should raise a "Detached" +// condition for the affected listener with a reason of "UnsupportedProtocol" +// +// Support: Extended +type GRPCRoute struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of GRPCRoute. + Spec GRPCRouteSpec `json:"spec,omitempty"` + + // Status defines the current state of GRPCRoute. + Status GRPCRouteStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// GRPCRouteList contains a list of GRPCRoute. +type GRPCRouteList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []GRPCRoute `json:"items"` +} + +// GRPCRouteStatus defines the observed state of GRPCRoute. +type GRPCRouteStatus struct { + RouteStatus `json:",inline"` +} + +// GRPCRouteSpec defines the desired state of GRPCRoute +type GRPCRouteSpec struct { + CommonRouteSpec `json:",inline"` + + // Hostnames defines a set of hostname that should match against the GRPC + // Host header to select a GRPCRoute to process the request. 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. + // + // If a hostname is specified by both the Listener and GRPCRoute, there + // must be at least one intersecting hostname for the GRPCRoute to be + // attached to the Listener. For example: + // + // * A Listener with `test.example.com` as the hostname matches GRPCRoutes + // 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 GRPCRoutes + // that have either not specified any hostnames or have specified at least + // one hostname that matches the Listener hostname. For example, + // `test.example.com` and `*.example.com` would both match. On the other + // hand, `example.com` and `test.example.net` would not match. + // + // 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 GRPCRoute have specified hostnames, any + // GRPCRoute hostnames that do not match the Listener hostname MUST be + // ignored. For example, if a Listener specified `*.example.com`, and the + // GRPCRoute specified `test.example.com` and `test.example.net`, + // `test.example.net` must not be considered for a match. + // + // If both the Listener and GRPCRoute have specified hostnames, and none + // match with the criteria above, then the GRPCRoute is not accepted. The + // implementation must raise an 'Accepted' Condition with a status of + // `False` in the corresponding RouteParentStatus. + // + // If a Route (A) of type HTTPRoute or GRPCRoute is attached to a + // Listener and that listener already has another Route (B) of the other + // type attached and the intersection of the hostnames of A and B is + // non-empty, then the implementation must reject Route A. That is, the + // implementation must raise an 'Accepted' condition with a status of + // 'False' in the corresponding RouteParentStatus. + // + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Hostnames []Hostname `json:"hostnames,omitempty"` + + // Rules are a list of GRPC matchers, filters and actions. + // + // +optional + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:default={{matches: {{method: {type: "Exact"}}}}} + Rules []GRPCRouteRule `json:"rules,omitempty"` +} + +// GRPCRouteRule defines semantics for matching an gRPC request based on +// conditions (matches), processing it (filters), and forwarding the request to +// an API object (backendRefs). +type GRPCRouteRule struct { + // Matches define conditions used for matching the rule against incoming + // gRPC 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: + // - method: + // service: foo.bar + // headers: + // values: + // version: 2 + // - method: + // service: foo.bar.v2 + // ``` + // + // For a request to match against this rule, a request should satisfy + // EITHER of the two conditions: + // + // - service of foo.bar AND contains the header `version: 2` + // - service of foo.bar.v2 + // + // See the documentation for GRPCRouteMatch on how to specify multiple + // match conditions that should be ANDed together. + // + // If no matches are specified, the implementation must match every gRPC request. + // + // Proxy or Load Balancer routing configuration generated from GRPCRoutes + // MUST prioritize rules based on the following criteria, continuing on + // ties. Merging must not be done between GRPCRoutes and HTTPRoutes. + // Precedence must be given to the rule with the largest number of: + // + // * Characters in a matching non-wildcard hostname. + // * Characters in a matching hostname. + // * Characters in a matching service. + // * Characters in a matching method. + // * Header matches. + // + // If ties still exist across multiple Routes, matching precedence MUST be + // determined in order of the following criteria, continuing on ties: + // + // * The oldest Route based on creation timestamp. + // * The Route appearing first in alphabetical order by + // "{namespace}/{name}". + // + // If ties still exist within the Route that has been given precedence, + // matching precedence MUST be granted to the first matching rule meeting + // the above criteria. + // + // +optional + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:default={{method: {type: "Exact"}}} + Matches []GRPCRouteMatch `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 a core filter multiple times has unspecified or custom + // conformance. + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Filters []GRPCRouteFilter `json:"filters,omitempty"` + + // BackendRefs defines the backend(s) where matching requests should be + // sent. + // + // An `UNIMPLEMENTED` status MUST be returned if there are no BackendRefs or filters + // specified that would result in a response being sent. + // + // A BackendRef is considered invalid when it refers to: + // + // * an unknown or unsupported kind of resource + // * a resource that does not exist + // * a resource in another namespace when the reference has not been + // explicitly allowed by a ReferenceGrant (or equivalent concept). + // + // When a BackendRef is invalid, `UNIMPLEMENTED` statuses 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 an `UNIMPLEMENTED` status. + // + // When a BackendRef refers to a Service that has no ready endpoints, it is + // recommended to return an `UNAVAILABLE` status. + // + // Support: Core for Kubernetes Service + // Support: Custom for any other resource + // + // Support for weight: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + BackendRefs []GRPCBackendRef `json:"backendRefs,omitempty"` +} + +// GRPCRouteMatch 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 gRPC request only if its service +// is `foo` AND it contains the `version: v1` header: +// +// “` +// matches: +// - method: +// +// type: Exact +// service: "foo" +// headers: +// - name: "version" +// value "v1" +// +// “` +type GRPCRouteMatch struct { + // Path specifies a gRPC request service/method matcher. If this field is not + // specified, all services and methods will match. + // + // +optional + // +kubebuilder:default={type: "Exact"} + Method *GRPCMethodMatch `json:"method,omitempty"` + + // Headers specifies gRPC 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 []GRPCHeaderMatch `json:"headers,omitempty"` +} + +// GRPCMethodMatch describes how to select a gRPC route by matching the gRPC +// request service and/or method. +// +// At least one of Service and Method must be a non-empty string. +type GRPCMethodMatch struct { + // Type specifies how to match against the service and/or method. + // Support: Core (Exact with service and method specified) + // + // Support Custom (Exact with method specified but no service specified) + // + // Support: Custom (RegularExpression) + // + // +optional + // +kubebuilder:default=Exact + Type *GRPCMethodMatchType `json:"type,omitempty"` + + // Value of the service to match against. If left empty or omitted, will + // match all services. + // + // At least one of Service and Method must be a non-empty string. + // +optional + // +kubebuilder:default="" + // +kubebuilder:validation:MaxLength=1024 + Service *string `json:"service,omitempty"` + + // Value of the method to match against. If left empty or omitted, will + // match all services. + // + // At least one of Service and Method must be a non-empty string. + // +optional + // +kubebuilder:default="" + // +kubebuilder:validation:MaxLength=1024 + Method *string `json:"method,omitempty"` +} + +// MethodMatchType specifies the semantics of how gRPC methods and services should be compared. +// Valid MethodMatchType values are: +// +// * "Exact" +// * "RegularExpression" +// +// Exact paths must be syntactically valid: +// +// - Must not contain `/` character +// +// +kubebuilder:validation:Enum=Exact;PathPrefix;RegularExpression +// +kubebuilder:validation:Enum=Exact;RegularExpression +type GRPCMethodMatchType string + +// GRPCHeaderMatch describes how to select a gRPC route by matching gRPC request +// headers. +type GRPCHeaderMatch struct { + // Type specifies how to match against the value of the header. + // + // +optional + // +kubebuilder:default=Exact + Type *HeaderMatchType `json:"type,omitempty"` + + // Name is the name of the gRPC Header to be matched. + // + // 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. + Name HeaderName `json:"name"` + + // Value is the value of the gRPC Header to be matched. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=4096 + Value string `json:"value"` +} + +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=256 +// +kubebuilder:validation:Pattern=`^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$` +type HeaderName string + +// GRPCRouteFilterType identifies a type of GRPCRoute filter. +type GRPCRouteFilterType string + +// GRPCRouteFilter defines processing steps that must be completed during the +// request or response lifecycle. GRPCRouteFilters 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. +type GRPCRouteFilter 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. + // + // - Custom: Filters that are defined and supported by specific vendors. + // In the future, filters showing convergence in behavior across multiple + // implementations will be considered for inclusion in extended or core + // conformance levels. Filter-specific configuration for such filters + // is specified using the ExtensionRef field. `Type` should be set to + // "ExtensionRef" for custom filters. + // + // Implementers are encouraged to define custom implementation types to + // extend the core API with implementation-specific behavior. + // + // If a reference to a custom filter type cannot be resolved, the filter + // MUST NOT be skipped. Instead, requests that would have been processed by + // that filter MUST receive a HTTP error response. + // + // +unionDiscriminator + // +kubebuilder:validation:Enum=RequestHeaderModifier;RequestMirror;ExtensionRef + // + Type GRPCRouteFilterType `json:"type"` + + // RequestHeaderModifier defines a schema for a filter that modifies request + // headers. + // + // Support: Core + // + // +optional + RequestHeaderModifier *HTTPRequestHeaderFilter `json:"requestHeaderModifier,omitempty"` + + // RequestMirror defines a schema for a filter that mirrors requests. + // Requests are sent to the specified destination, but responses from + // that destination are ignored. + // + // Support: Extended + // + // +optional + RequestMirror *HTTPRequestMirrorFilter `json:"requestMirror,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. + // + // Support: Implementation-specific + // + // +optional + ExtensionRef *LocalObjectReference `json:"extensionRef,omitempty"` +} + +// GRPCBackendRef defines how a GRPCRoute should forward a gRPC request. +type GRPCBackendRef struct { + // BackendRef is a reference to a backend to forward matched requests to. + // + // If the referent cannot be found, this GRPCBackendRef is invalid and must + // be dropped from the Gateway. The controller must ensure the + // "ResolvedRefs" condition on the Route 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 covered by a ReferencePolicy, the controller must ensure the + // "ResolvedRefs" condition on the Route is set to `status: False`, + // with the "RefNotPermitted" reason and not configure this backend in the + // underlying implementation. + // + // In either error case, the Message of the `ResolvedRefs` Condition + // should be used to provide more detail about the problem. + // + // Support: Custom + // + // +optional + BackendRefs 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: Custom (For broader support of filters, use the Filters field + // in GRPCRouteRule.) + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Filters []GRPCRouteFilter `json:"filters,omitempty"` +} diff --git a/apis/v1alpha2/httproute_types.go b/apis/v1alpha2/httproute_types.go index 082794d1ca..da8295c08c 100644 --- a/apis/v1alpha2/httproute_types.go +++ b/apis/v1alpha2/httproute_types.go @@ -93,6 +93,13 @@ type HTTPRouteSpec struct { // implementation must raise an 'Accepted' Condition with a status of // `False` in the corresponding RouteParentStatus. // + // If a Route (A) of type HTTPRoute or GRPCRoute is attached to a + // Listener and that listener already has another Route (B) of the other + // type attached and the intersection of the hostnames of A and B is + // non-empty, then the implementation must reject Route A. That is, the + // implementation must raise an 'Accepted' condition with a status of + // 'False' in the corresponding RouteParentStatus. + // // Support: Core // // +optional @@ -333,7 +340,9 @@ const ( // Invalid values include: // // * ":method" - ":" is an invalid character. This means that HTTP/2 pseudo -// headers are not currently supported by this type. +// +// headers are not currently supported by this type. +// // * "/invalid" - "/" is an invalid character // // +kubebuilder:validation:MinLength=1 @@ -476,14 +485,16 @@ const ( // 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" -// ``` +// +// 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. diff --git a/apis/v1alpha2/referencegrant_types.go b/apis/v1alpha2/referencegrant_types.go index 9da3057486..8b777c7e47 100644 --- a/apis/v1alpha2/referencegrant_types.go +++ b/apis/v1alpha2/referencegrant_types.go @@ -36,7 +36,6 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // Gateway-route attachment) require a ReferenceGrant. // // Support: Core -// type ReferenceGrant struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/apis/v1alpha2/referencepolicy_types.go b/apis/v1alpha2/referencepolicy_types.go index dc41701a8e..17eb4039c3 100644 --- a/apis/v1alpha2/referencepolicy_types.go +++ b/apis/v1alpha2/referencepolicy_types.go @@ -40,7 +40,6 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // Gateway-route attachment) require a ReferenceGrant. // // Support: Core -// type ReferencePolicy struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/apis/v1alpha2/shared_types.go b/apis/v1alpha2/shared_types.go index 2ac4ae8ac9..84b10972a6 100644 --- a/apis/v1alpha2/shared_types.go +++ b/apis/v1alpha2/shared_types.go @@ -333,7 +333,8 @@ type RouteStatus struct { // // 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. +// +// 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 diff --git a/apis/v1alpha2/validation/gateway.go b/apis/v1alpha2/validation/gateway.go index b6dd4c9407..0a875b9a55 100644 --- a/apis/v1alpha2/validation/gateway.go +++ b/apis/v1alpha2/validation/gateway.go @@ -40,7 +40,8 @@ var ( // ValidateGateway validates gw according to the Gateway API specification. // For additional details of the Gateway spec, refer to: -// https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.Gateway +// +// https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.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. diff --git a/apis/v1alpha2/validation/httproute.go b/apis/v1alpha2/validation/httproute.go index 2b94ea0be3..1e723c20b1 100644 --- a/apis/v1alpha2/validation/httproute.go +++ b/apis/v1alpha2/validation/httproute.go @@ -209,7 +209,7 @@ func validateHTTPQueryParamMatches(matches []gatewayv1a2.HTTPQueryParamMatch, pa } // validateHTTPRouteFilterTypeMatchesValue validates that only the expected fields are -//// set for the specified filter type. +// // set for the specified filter type. func validateHTTPRouteFilterTypeMatchesValue(filter gatewayv1a2.HTTPRouteFilter, path *field.Path) field.ErrorList { var errs field.ErrorList if filter.ExtensionRef != nil && filter.Type != gatewayv1a2.HTTPRouteFilterExtensionRef { diff --git a/apis/v1alpha2/zz_generated.deepcopy.go b/apis/v1alpha2/zz_generated.deepcopy.go index b2b4f028ae..6d54d29f12 100644 --- a/apis/v1alpha2/zz_generated.deepcopy.go +++ b/apis/v1alpha2/zz_generated.deepcopy.go @@ -131,6 +131,275 @@ func (in *CommonRouteSpec) DeepCopy() *CommonRouteSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCBackendRef) DeepCopyInto(out *GRPCBackendRef) { + *out = *in + in.BackendRefs.DeepCopyInto(&out.BackendRefs) + if in.Filters != nil { + in, out := &in.Filters, &out.Filters + *out = make([]GRPCRouteFilter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCBackendRef. +func (in *GRPCBackendRef) DeepCopy() *GRPCBackendRef { + if in == nil { + return nil + } + out := new(GRPCBackendRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCHeaderMatch) DeepCopyInto(out *GRPCHeaderMatch) { + *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 GRPCHeaderMatch. +func (in *GRPCHeaderMatch) DeepCopy() *GRPCHeaderMatch { + if in == nil { + return nil + } + out := new(GRPCHeaderMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCMethodMatch) DeepCopyInto(out *GRPCMethodMatch) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(GRPCMethodMatchType) + **out = **in + } + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(string) + **out = **in + } + if in.Method != nil { + in, out := &in.Method, &out.Method + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCMethodMatch. +func (in *GRPCMethodMatch) DeepCopy() *GRPCMethodMatch { + if in == nil { + return nil + } + out := new(GRPCMethodMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCRoute) DeepCopyInto(out *GRPCRoute) { + *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 GRPCRoute. +func (in *GRPCRoute) DeepCopy() *GRPCRoute { + if in == nil { + return nil + } + out := new(GRPCRoute) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GRPCRoute) 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 *GRPCRouteFilter) DeepCopyInto(out *GRPCRouteFilter) { + *out = *in + if in.RequestHeaderModifier != nil { + in, out := &in.RequestHeaderModifier, &out.RequestHeaderModifier + *out = new(HTTPRequestHeaderFilter) + (*in).DeepCopyInto(*out) + } + if in.RequestMirror != nil { + in, out := &in.RequestMirror, &out.RequestMirror + *out = new(HTTPRequestMirrorFilter) + (*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 GRPCRouteFilter. +func (in *GRPCRouteFilter) DeepCopy() *GRPCRouteFilter { + if in == nil { + return nil + } + out := new(GRPCRouteFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCRouteList) DeepCopyInto(out *GRPCRouteList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GRPCRoute, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteList. +func (in *GRPCRouteList) DeepCopy() *GRPCRouteList { + if in == nil { + return nil + } + out := new(GRPCRouteList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GRPCRouteList) 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 *GRPCRouteMatch) DeepCopyInto(out *GRPCRouteMatch) { + *out = *in + if in.Method != nil { + in, out := &in.Method, &out.Method + *out = new(GRPCMethodMatch) + (*in).DeepCopyInto(*out) + } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]GRPCHeaderMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteMatch. +func (in *GRPCRouteMatch) DeepCopy() *GRPCRouteMatch { + if in == nil { + return nil + } + out := new(GRPCRouteMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCRouteRule) DeepCopyInto(out *GRPCRouteRule) { + *out = *in + if in.Matches != nil { + in, out := &in.Matches, &out.Matches + *out = make([]GRPCRouteMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Filters != nil { + in, out := &in.Filters, &out.Filters + *out = make([]GRPCRouteFilter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.BackendRefs != nil { + in, out := &in.BackendRefs, &out.BackendRefs + *out = make([]GRPCBackendRef, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteRule. +func (in *GRPCRouteRule) DeepCopy() *GRPCRouteRule { + if in == nil { + return nil + } + out := new(GRPCRouteRule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCRouteSpec) DeepCopyInto(out *GRPCRouteSpec) { + *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([]GRPCRouteRule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteSpec. +func (in *GRPCRouteSpec) DeepCopy() *GRPCRouteSpec { + if in == nil { + return nil + } + out := new(GRPCRouteSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCRouteStatus) DeepCopyInto(out *GRPCRouteStatus) { + *out = *in + in.RouteStatus.DeepCopyInto(&out.RouteStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteStatus. +func (in *GRPCRouteStatus) DeepCopy() *GRPCRouteStatus { + if in == nil { + return nil + } + out := new(GRPCRouteStatus) + 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 diff --git a/apis/v1alpha2/zz_generated.register.go b/apis/v1alpha2/zz_generated.register.go index ba6c8150ac..9dcde248f0 100644 --- a/apis/v1alpha2/zz_generated.register.go +++ b/apis/v1alpha2/zz_generated.register.go @@ -58,6 +58,8 @@ func init() { // Adds the list of known types to Scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, + &GRPCRoute{}, + &GRPCRouteList{}, &Gateway{}, &GatewayClass{}, &GatewayClassList{}, diff --git a/apis/v1beta1/httproute_types.go b/apis/v1beta1/httproute_types.go index 02faedad8d..d841610b57 100644 --- a/apis/v1beta1/httproute_types.go +++ b/apis/v1beta1/httproute_types.go @@ -332,7 +332,9 @@ const ( // Invalid values include: // // * ":method" - ":" is an invalid character. This means that HTTP/2 pseudo -// headers are not currently supported by this type. +// +// headers are not currently supported by this type. +// // * "/invalid" - "/" is an invalid character // // +kubebuilder:validation:MinLength=1 @@ -475,14 +477,16 @@ const ( // 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" -// ``` +// +// 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. diff --git a/apis/v1beta1/shared_types.go b/apis/v1beta1/shared_types.go index a92cf8c116..d02002ed52 100644 --- a/apis/v1beta1/shared_types.go +++ b/apis/v1beta1/shared_types.go @@ -333,7 +333,8 @@ type RouteStatus struct { // // 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. +// +// 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 diff --git a/apis/v1beta1/validation/gateway.go b/apis/v1beta1/validation/gateway.go index 512a5b7c67..c1f93c9555 100644 --- a/apis/v1beta1/validation/gateway.go +++ b/apis/v1beta1/validation/gateway.go @@ -40,7 +40,8 @@ var ( // 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 +// +// 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. diff --git a/apis/v1beta1/validation/httproute.go b/apis/v1beta1/validation/httproute.go index 974aa9e3ce..a96e266385 100644 --- a/apis/v1beta1/validation/httproute.go +++ b/apis/v1beta1/validation/httproute.go @@ -209,7 +209,7 @@ func validateHTTPQueryParamMatches(matches []gatewayv1a2.HTTPQueryParamMatch, pa } // validateHTTPRouteFilterTypeMatchesValue validates that only the expected fields are -//// set for the specified filter type. +// // set for the specified filter type. func validateHTTPRouteFilterTypeMatchesValue(filter gatewayv1a2.HTTPRouteFilter, path *field.Path) field.ErrorList { var errs field.ErrorList if filter.ExtensionRef != nil && filter.Type != gatewayv1a2.HTTPRouteFilterExtensionRef { diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml new file mode 100644 index 0000000000..165dba967d --- /dev/null +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -0,0 +1,1227 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1086 + gateway.networking.k8s.io/bundle-version: v0.5.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: grpcroutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: GRPCRoute + listKind: GRPCRouteList + plural: grpcroutes + singular: grpcroute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: "GRPCRoute provides a way to route gRPC requests. This includes + the capability to match requests by hostname, gRPC service, gRPC method, + or HTTP/2 header. Filters can be used to specify additional processing steps. + Backends specify where matching requests should be routed. \n Implementations + supporting `GRPCRoute` with the `HTTPS` `ProtocolType` must accept HTTP/2 + connections without an initial upgrade from HTTP/1.1. If the implementation + does not support this, then it should raise a \"Detached\" condition for + the affected listener with a reason of \"UnsupportedProtocol\" \n Implementations + supporting `GRPCRoute` with the `HTTP` `ProtocolType` must support cleartext + HTTP/2 without an initial upgrade from HTTP/1.1. If the implementation does + not support this, then it should raise a \"Detached\" condition for the + affected listener with a reason of \"UnsupportedProtocol\" \n Support: Extended" + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GRPCRoute. + properties: + hostnames: + description: "Hostnames defines a set of hostname that should match + against the GRPC Host header to select a GRPCRoute to process the + request. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may + be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n If a hostname is specified + by both the Listener and GRPCRoute, there must be at least one intersecting + hostname for the GRPCRoute to be attached to the Listener. For example: + \n * A Listener with `test.example.com` as the hostname matches + GRPCRoutes 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 GRPCRoutes + \ that have either not specified any hostnames or have specified + at least one hostname that matches the Listener hostname. For + example, `test.example.com` and `*.example.com` would both match. + On the other hand, `example.com` and `test.example.net` would + not match. \n 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`. \n If both the Listener and GRPCRoute have + specified hostnames, any GRPCRoute hostnames that do not match the + Listener hostname MUST be ignored. For example, if a Listener specified + `*.example.com`, and the GRPCRoute specified `test.example.com` + and `test.example.net`, `test.example.net` must not be considered + for a match. \n If both the Listener and GRPCRoute have specified + hostnames, and none match with the criteria above, then the GRPCRoute + is not accepted. The implementation must raise an 'Accepted' Condition + with a status of `False` in the corresponding RouteParentStatus. + \n If a Route (A) of type HTTPRoute or GRPCRoute is attached to + a Listener and that listener already has another Route (B) of the + other type attached and the intersection of the hostnames of A and + B is non-empty, then the implementation must reject Route A. That + is, the implementation must raise an 'Accepted' condition with a + status of 'False' in the corresponding RouteParentStatus. \n Support: + Core" + items: + description: "Hostname is the fully qualified domain name of a network + host. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname + may be prefixed with a wildcard label (`*.`). The wildcard \n + \tlabel must appear by itself as the first label. \n Hostname + can be \"precise\" which is a domain name without the terminating + dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", + which is a domain name prefixed with a single wildcard label (e.g. + `*.example.com`). \n Note that as per RFC1035 and RFC1123, a *label* + must consist of lower case alphanumeric characters or '-', and + must start and end with an alphanumeric character. No other punctuation + is allowed." + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) + that a Route wants to be attached to. Note that the referenced parent + resource needs to allow this for the attachment to be complete. + For Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. \n The only kind of parent resource + with \"Core\" support is Gateway. This API may be extended in the + future to support additional kinds of parent resources such as one + of the route kinds. \n It is invalid to reference an identical parent + more than once. It is valid to reference multiple distinct sections + within the same parent resource, such as 2 Listeners within a Gateway. + \n It is possible to separately reference multiple distinct objects + that may be collapsed by an implementation. For example, some implementations + may choose to merge compatible Gateway Listeners together. If that + is the case, the list of routes attached to those resources should + also be merged." + items: + description: "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 with \"Core\" support + is Gateway. This API may be extended in the future to support + additional kinds of parent resources, such as HTTPRoute. \n The + API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n Support: Core + (Gateway) \n Support: Custom (Other Resources)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified (or empty string), this refers to the local namespace + of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It + can be interpreted differently based on the type of parent + resource. \n 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. \n Implementations MAY choose + to support other parent resources. Implementations supporting + other types of parent resources MUST clearly document how/if + Port is interpreted. \n 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. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match both + specified values. \n Implementations MAY choose to support + attaching Routes to other resources. If that is the case, + they MUST clearly document how SectionName is interpreted. + \n When unspecified (empty string), this will reference the + entire resource. For the purpose of status, an attachment + is considered successful if at least one section in the parent + resource accepts it. For example, Gateway listeners can restrict + which Routes can attach to them by Route kind, namespace, + or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this + Route, the Route MUST be considered detached from the Gateway. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + rules: + default: + - matches: + - method: + type: Exact + description: Rules are a list of GRPC matchers, filters and actions. + items: + description: GRPCRouteRule defines semantics for matching an gRPC + request based on conditions (matches), processing it (filters), + and forwarding the request to an API object (backendRefs). + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching + requests should be sent. \n An `UNIMPLEMENTED` status MUST + be returned if there are no BackendRefs or filters specified + that would result in a response being sent. \n A BackendRef + is considered invalid when it refers to: \n * an unknown or + unsupported kind of resource * a resource that does not exist + * a resource in another namespace when the reference has not + been explicitly allowed by a ReferenceGrant (or equivalent + concept). \n When a BackendRef is invalid, `UNIMPLEMENTED` + statuses 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 an `UNIMPLEMENTED` status. \n When a BackendRef + refers to a Service that has no ready endpoints, it is recommended + to return an `UNAVAILABLE` status. \n Support: Core for Kubernetes + Service Support: Custom for any other resource \n Support + for weight: Core" + items: + description: GRPCBackendRef defines how a GRPCRoute should + forward a gRPC request. + properties: + filters: + description: "Filters defined at this level should be + executed if and only if the request is being forwarded + to the backend defined here. \n Support: Custom (For + broader support of filters, use the Filters field in + GRPCRouteRule.)" + items: + description: GRPCRouteFilter defines processing steps + that must be completed during the request or response + lifecycle. GRPCRouteFilters are meant as an extension + point to express processing that may be done in Gateway + implementations. Some examples include request or + response modification, implementing authentication + strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type + of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific + extension to the \"filter\" behavior. For example, + resource \"myroutefilter\" in group \"networking.example.net\"). + ExtensionRef MUST NOT be used for core and extended + filters. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. + For example, "networking.k8s.io". When unspecified + (empty string), core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema + for a filter that modifies request headers. \n + Support: Core" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It + appends to any existing values associated + with the header name. \n Input: GET /foo + HTTP/1.1 my-header: foo \n Config: add: + \ - name: \"my-header\" value: \"bar\" + \n Output: GET /foo HTTP/1.1 my-header: + foo my-header: bar" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from + the HTTP request before the action. The value + of Remove is a list of HTTP header names. + Note that the header names are case-insensitive + (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: + foo my-header2: bar my-header3: baz \n + Config: remove: [\"my-header1\", \"my-header3\"] + \n Output: GET /foo HTTP/1.1 my-header2: + bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with + the given header (name, value) before the + action. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: set: - name: \"my-header\" + \ value: \"bar\" \n Output: GET /foo + HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for + a filter that mirrors requests. Requests are sent + to the specified destination, but responses from + that destination are ignored. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource + where mirrored requests are sent. \n If the + referent cannot be found, this BackendRef + is invalid and must be dropped from the Gateway. + The controller must ensure the \"ResolvedRefs\" + condition on the Route status is set to `status: + False` and not configure this backend in the + underlying implementation. \n If there is + a cross-namespace reference to an *existing* + object that is not allowed by a 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. \n In either error case, the + Message of the `ResolvedRefs` Condition should + be used to provide more detail about the problem. + \n Support: Extended for Kubernetes Service + \n Support: Custom for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "networking.k8s.io". When + unspecified (empty string), core API group + is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: Kind is kind of the referent. + For example "HTTPRoute" or "Service". + Defaults to "Service" when not specified. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace + of the backend. When unspecified, the + local namespace is inferred. \n Note that + when a different namespace is specified, + a ReferenceGrant object with ReferenceGrantTo.Kind=Service + is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferenceGrant + documentation for details. \n Support: + Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination + port number to use for this resource. + Port is required when the referent is + a Kubernetes Service. For other resources, + destination port might be derived from + the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + required: + - backendRef + type: object + type: + description: "Type identifies the type of filter + to apply. As with other API fields, types are + classified into three conformance levels: \n - + Core: Filter types and their corresponding configuration + defined by \"Support: Core\" in this package, + e.g. \"RequestHeaderModifier\". All implementations + must support core filters. \n - Extended: Filter + types and their corresponding configuration defined + by \"Support: Extended\" in this package, e.g. + \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Custom: Filters + that are defined and supported by specific vendors. + \ In the future, filters showing convergence + in behavior across multiple implementations + will be considered for inclusion in extended or + core conformance levels. Filter-specific configuration + for such filters is specified using the ExtensionRef + field. `Type` should be set to \"ExtensionRef\" + for custom filters. \n Implementers are encouraged + to define custom implementation types to extend + the core API with implementation-specific behavior. + \n If a reference to a custom filter type cannot + be resolved, the filter MUST NOT be skipped. Instead, + requests that would have been processed by that + filter MUST receive a HTTP error response. \n " + enum: + - RequestHeaderModifier + - RequestMirror + - ExtensionRef + type: string + required: + - type + type: object + maxItems: 16 + type: array + group: + default: "" + description: Group is the group of the referent. For example, + "networking.k8s.io". When unspecified (empty string), + core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". Defaults to "Service" when + not specified. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a different namespace is specified, a + ReferenceGrant object with ReferenceGrantTo.Kind=Service + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number + to use for this resource. Port is required when the + referent is a Kubernetes Service. For other resources, + destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests + forwarded to the referenced backend. This is computed + as weight/(sum of all weights in this BackendRefs list). + For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision + an implementation supports. Weight is not a percentage + and the sum of weights does not need to equal 100. \n + If only one backend is specified and it has a weight + greater than 0, 100% of the traffic is forwarded to + that backend. If weight is set to 0, no traffic should + be forwarded for this entry. If unspecified, weight + defaults to 1. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + maxItems: 16 + type: array + filters: + description: "Filters define the filters that are applied to + requests that match this rule. \n The effects of ordering + of multiple behaviors are currently unspecified. This can + change in the future based on feedback during the alpha stage. + \n Conformance-levels at this level are defined based on the + type of filter: \n - ALL core filters MUST be supported by + all implementations. - Implementers are encouraged to support + extended filters. - Implementation-specific custom filters + have no API guarantees across implementations. \n Specifying + a core filter multiple times has unspecified or custom conformance. + Support: Core" + items: + description: GRPCRouteFilter defines processing steps that + must be completed during the request or response lifecycle. + GRPCRouteFilters are meant as an extension point to express + processing that may be done in Gateway implementations. + Some examples include request or response modification, + implementing authentication strategies, rate-limiting, and + traffic shaping. API guarantee/conformance is defined based + on the type of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific + extension to the \"filter\" behavior. For example, + resource \"myroutefilter\" in group \"networking.example.net\"). + ExtensionRef MUST NOT be used for core and extended + filters. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. For + example, "networking.k8s.io". When unspecified (empty + string), core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for + a filter that modifies request headers. \n Support: + Core" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It appends + to any existing values associated with the header + name. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: add: - name: \"my-header\" value: + \"bar\" \n Output: GET /foo HTTP/1.1 my-header: + foo my-header: bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the + HTTP request before the action. The value of Remove + is a list of HTTP header names. Note that the header + names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo + \ my-header2: bar my-header3: baz \n Config: + \ remove: [\"my-header1\", \"my-header3\"] \n Output: + \ GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with the + given header (name, value) before the action. \n + Input: GET /foo HTTP/1.1 my-header: foo \n Config: + \ set: - name: \"my-header\" value: \"bar\" + \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for a filter + that mirrors requests. Requests are sent to the specified + destination, but responses from that destination are + ignored. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where + mirrored requests are sent. \n If the referent cannot + be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure + the \"ResolvedRefs\" condition on the Route status + is set to `status: False` and not configure this + backend in the underlying implementation. \n If + there is a cross-namespace reference to an *existing* + object that is not allowed by a 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. \n + In either error case, the Message of the `ResolvedRefs` + Condition should be used to provide more detail + about the problem. \n Support: Extended for Kubernetes + Service \n Support: Custom for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "networking.k8s.io". When unspecified + (empty string), core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". Defaults to + "Service" when not specified. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the + backend. When unspecified, the local namespace + is inferred. \n Note that when a different namespace + is specified, a ReferenceGrant object with ReferenceGrantTo.Kind=Service + is required in the referent namespace to allow + that namespace's owner to accept the reference. + See the ReferenceGrant documentation for details. + \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port + number to use for this resource. Port is required + when the referent is a Kubernetes Service. For + other resources, destination port might be derived + from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + required: + - backendRef + type: object + type: + description: "Type identifies the type of filter to apply. + As with other API fields, types are classified into + three conformance levels: \n - Core: Filter types and + their corresponding configuration defined by \"Support: + Core\" in this package, e.g. \"RequestHeaderModifier\". + All implementations must support core filters. \n + - Extended: Filter types and their corresponding configuration + defined by \"Support: Extended\" in this package, + e.g. \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Custom: Filters that + are defined and supported by specific vendors. In + the future, filters showing convergence in behavior + across multiple implementations will be considered + for inclusion in extended or core conformance levels. + Filter-specific configuration for such filters is + specified using the ExtensionRef field. `Type` should + be set to \"ExtensionRef\" for custom filters. \n + Implementers are encouraged to define custom implementation + types to extend the core API with implementation-specific + behavior. \n If a reference to a custom filter type + cannot be resolved, the filter MUST NOT be skipped. + Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. \n " + enum: + - RequestHeaderModifier + - RequestMirror + - ExtensionRef + type: string + required: + - type + type: object + maxItems: 16 + type: array + matches: + default: + - method: + type: Exact + description: "Matches define conditions used for matching the + rule against incoming gRPC requests. Each match is independent, + i.e. this rule will be matched if **any** one of the matches + is satisfied. \n For example, take the following matches configuration: + \n ``` matches: - method: service: foo.bar headers: + \ values: version: 2 - method: service: foo.bar.v2 + ``` \n For a request to match against this rule, a request + should satisfy EITHER of the two conditions: \n - service + of foo.bar AND contains the header `version: 2` - service + of foo.bar.v2 \n See the documentation for GRPCRouteMatch + on how to specify multiple match conditions that should be + ANDed together. \n If no matches are specified, the implementation + must match every gRPC request. \n Proxy or Load Balancer routing + configuration generated from GRPCRoutes MUST prioritize rules + based on the following criteria, continuing on ties. Merging + must not be done between GRPCRoutes and HTTPRoutes. Precedence + must be given to the rule with the largest number of: \n * + Characters in a matching non-wildcard hostname. * Characters + in a matching hostname. * Characters in a matching service. + * Characters in a matching method. * Header matches. \n If + ties still exist across multiple Routes, matching precedence + MUST be determined in order of the following criteria, continuing + on ties: \n * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by \"{namespace}/{name}\". + \n If ties still exist within the Route that has been given + precedence, matching precedence MUST be granted to the first + matching rule meeting the above criteria." + items: + description: "GRPCRouteMatch defines the predicate used to + match requests to a given action. Multiple match types are + ANDed together, i.e. the match will evaluate to true only + if all conditions are satisfied. \n For example, the match + below will match a gRPC request only if its service is `foo` + AND it contains the `version: v1` header: \n “` matches: + - method: \n \t type: Exact \t service: \"foo\" \theaders: + \t- name: \"version\" \t value \"v1\" \n “`" + properties: + headers: + description: Headers specifies gRPC request header matchers. + Multiple match values are ANDed together, meaning, a + request must match all the specified headers to select + the route. + items: + description: GRPCHeaderMatch describes how to select + a gRPC route by matching gRPC request headers. + properties: + name: + description: "Name is the name of the gRPC Header + to be matched. \n If multiple entries specify + equivalent header names, only the first entry + with an equivalent name MUST be considered for + a match. Subsequent entries with an equivalent + header name MUST be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: Type specifies how to match against + the value of the header. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of the gRPC Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + default: + type: Exact + description: Path specifies a gRPC request service/method + matcher. If this field is not specified, all services + and methods will match. + properties: + method: + default: "" + description: "Value of the method to match against. + If left empty or omitted, will match all services. + \n At least one of Service and Method must be a + non-empty string." + maxLength: 1024 + type: string + service: + default: "" + description: "Value of the service to match against. + If left empty or omitted, will match all services. + \n At least one of Service and Method must be a + non-empty string." + maxLength: 1024 + type: string + type: + default: Exact + description: "Type specifies how to match against + the service and/or method. Support: Core (Exact + with service and method specified) \n Support Custom + (Exact with method specified but no service specified) + \n Support: Custom (RegularExpression)" + enum: + - Exact + - RegularExpression + type: string + type: object + type: object + maxItems: 8 + type: array + type: object + maxItems: 16 + type: array + type: object + status: + description: Status defines the current state of GRPCRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) + that are associated with the route, and the status of the route + with respect to each parent. When this route attaches to a parent, + the controller that manages the parent must add an entry to this + list when the controller first sees the route and should update + the entry as appropriate when the route or gateway is modified. + \n Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this + API can only populate Route status for the Gateways/parent resources + they are responsible for. \n A maximum of 32 Gateways will be represented + in this list. An empty list means the route has not been attached + to any Gateway." + items: + description: RouteParentStatus describes the status of a route with + respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with + respect to the Gateway. Note that the route's availability + is also subject to the Gateway's own status conditions and + listener status. \n If the Route's ParentRef specifies an + existing Gateway that supports Routes of this kind AND that + Gateway's controller has sufficient access, then that Gateway's + controller MUST set the \"Accepted\" condition on the Route, + to indicate whether the route has been accepted or rejected + by the Gateway, and why. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + \n 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." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec + that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n Support: + Core (Gateway) \n Support: Custom (Other Resources)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified (or empty string), this refers to the + local namespace of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. + It can be interpreted differently based on the type of + parent resource. \n 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. \n Implementations MAY choose to + support other parent resources. Implementations supporting + other types of parent resources MUST clearly document + how/if Port is interpreted. \n 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. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name. When both Port (experimental) and SectionName are + specified, the name and port of the selected listener + must match both specified values. \n Implementations MAY + choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this + will reference the entire resource. For the purpose of + status, an attachment is considered successful if at least + one section in the parent resource accepts it. For example, + Gateway listeners can restrict which Routes can attach + to them by Route kind, namespace, or hostname. If 1 of + 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 4b8ebaf58b..a32fbad977 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -77,19 +77,26 @@ spec: have specified hostnames, and none match with the criteria above, then the HTTPRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding - RouteParentStatus. \n Support: Core" + RouteParentStatus. \n If a Route (A) of type HTTPRoute or GRPCRoute + is attached to a Listener and that listener already has another + Route (B) of the other type attached and the intersection of the + hostnames of A and B is non-empty, then the implementation must + reject Route A. That is, the implementation must raise an 'Accepted' + condition with a status of 'False' in the corresponding RouteParentStatus. + \n Support: Core" items: description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname - may be prefixed with a wildcard label (`*.`). The wildcard label - must appear by itself as the first label. \n Hostname can be \"precise\" - which is a domain name without the terminating dot of a network - host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain - name prefixed with a single wildcard label (e.g. `*.example.com`). - \n Note that as per RFC1035 and RFC1123, a *label* must consist - of lower case alphanumeric characters or '-', and must start and - end with an alphanumeric character. No other punctuation is allowed." + may be prefixed with a wildcard label (`*.`). The wildcard \n + \tlabel must appear by itself as the first label. \n Hostname + can be \"precise\" which is a domain name without the terminating + dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", + which is a domain name prefixed with a single wildcard label (e.g. + `*.example.com`). \n Note that as per RFC1035 and RFC1123, a *label* + must consist of lower case alphanumeric characters or '-', and + must start and end with an alphanumeric character. No other punctuation + is allowed." maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -1227,8 +1234,8 @@ spec: if all conditions are satisfied. \n For example, the match below will match a HTTP request only if its path starts with `/foo` AND it contains the `version: v1` header: \n - ``` match: path: value: \"/foo\" headers: - name: - \"version\" value \"v1\" ```" + “` match: \n \tpath: \t value: \"/foo\" \theaders: \t- + name: \"version\" \t value \"v1\" \n “`" properties: headers: description: Headers specifies HTTP request header matchers. @@ -1681,14 +1688,15 @@ spec: description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname - may be prefixed with a wildcard label (`*.`). The wildcard label - must appear by itself as the first label. \n Hostname can be \"precise\" - which is a domain name without the terminating dot of a network - host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain - name prefixed with a single wildcard label (e.g. `*.example.com`). - \n Note that as per RFC1035 and RFC1123, a *label* must consist - of lower case alphanumeric characters or '-', and must start and - end with an alphanumeric character. No other punctuation is allowed." + may be prefixed with a wildcard label (`*.`). The wildcard \n + \tlabel must appear by itself as the first label. \n Hostname + can be \"precise\" which is a domain name without the terminating + dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", + which is a domain name prefixed with a single wildcard label (e.g. + `*.example.com`). \n Note that as per RFC1035 and RFC1123, a *label* + must consist of lower case alphanumeric characters or '-', and + must start and end with an alphanumeric character. No other punctuation + is allowed." maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -2824,8 +2832,8 @@ spec: if all conditions are satisfied. \n For example, the match below will match a HTTP request only if its path starts with `/foo` AND it contains the `version: v1` header: \n - ``` match: path: value: \"/foo\" headers: - name: - \"version\" value \"v1\" ```" + “` match: \n \tpath: \t value: \"/foo\" \theaders: \t- + name: \"version\" \t value \"v1\" \n “`" properties: headers: description: Headers specifies HTTP request header matchers. diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index 78ea7b88ec..8c0b0534de 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -76,14 +76,15 @@ spec: description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname - may be prefixed with a wildcard label (`*.`). The wildcard label - must appear by itself as the first label. \n Hostname can be \"precise\" - which is a domain name without the terminating dot of a network - host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain - name prefixed with a single wildcard label (e.g. `*.example.com`). - \n Note that as per RFC1035 and RFC1123, a *label* must consist - of lower case alphanumeric characters or '-', and must start and - end with an alphanumeric character. No other punctuation is allowed." + may be prefixed with a wildcard label (`*.`). The wildcard \n + \tlabel must appear by itself as the first label. \n Hostname + can be \"precise\" which is a domain name without the terminating + dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", + which is a domain name prefixed with a single wildcard label (e.g. + `*.example.com`). \n Note that as per RFC1035 and RFC1123, a *label* + must consist of lower case alphanumeric characters or '-', and + must start and end with an alphanumeric character. No other punctuation + is allowed." maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ diff --git a/config/crd/experimental/kustomization.yaml b/config/crd/experimental/kustomization.yaml index 92ba09114f..9ce8a755d9 100644 --- a/config/crd/experimental/kustomization.yaml +++ b/config/crd/experimental/kustomization.yaml @@ -7,3 +7,4 @@ resources: - gateway.networking.k8s.io_tcproutes.yaml - gateway.networking.k8s.io_tlsroutes.yaml - gateway.networking.k8s.io_udproutes.yaml +- gateway.networking.k8s.io_grpcroutes.yaml diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index 2fac441686..8329a2760f 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -77,19 +77,26 @@ spec: have specified hostnames, and none match with the criteria above, then the HTTPRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding - RouteParentStatus. \n Support: Core" + RouteParentStatus. \n If a Route (A) of type HTTPRoute or GRPCRoute + is attached to a Listener and that listener already has another + Route (B) of the other type attached and the intersection of the + hostnames of A and B is non-empty, then the implementation must + reject Route A. That is, the implementation must raise an 'Accepted' + condition with a status of 'False' in the corresponding RouteParentStatus. + \n Support: Core" items: description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname - may be prefixed with a wildcard label (`*.`). The wildcard label - must appear by itself as the first label. \n Hostname can be \"precise\" - which is a domain name without the terminating dot of a network - host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain - name prefixed with a single wildcard label (e.g. `*.example.com`). - \n Note that as per RFC1035 and RFC1123, a *label* must consist - of lower case alphanumeric characters or '-', and must start and - end with an alphanumeric character. No other punctuation is allowed." + may be prefixed with a wildcard label (`*.`). The wildcard \n + \tlabel must appear by itself as the first label. \n Hostname + can be \"precise\" which is a domain name without the terminating + dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", + which is a domain name prefixed with a single wildcard label (e.g. + `*.example.com`). \n Note that as per RFC1035 and RFC1123, a *label* + must consist of lower case alphanumeric characters or '-', and + must start and end with an alphanumeric character. No other punctuation + is allowed." maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -984,8 +991,8 @@ spec: if all conditions are satisfied. \n For example, the match below will match a HTTP request only if its path starts with `/foo` AND it contains the `version: v1` header: \n - ``` match: path: value: \"/foo\" headers: - name: - \"version\" value \"v1\" ```" + “` match: \n \tpath: \t value: \"/foo\" \theaders: \t- + name: \"version\" \t value \"v1\" \n “`" properties: headers: description: Headers specifies HTTP request header matchers. @@ -1410,14 +1417,15 @@ spec: description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname - may be prefixed with a wildcard label (`*.`). The wildcard label - must appear by itself as the first label. \n Hostname can be \"precise\" - which is a domain name without the terminating dot of a network - host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain - name prefixed with a single wildcard label (e.g. `*.example.com`). - \n Note that as per RFC1035 and RFC1123, a *label* must consist - of lower case alphanumeric characters or '-', and must start and - end with an alphanumeric character. No other punctuation is allowed." + may be prefixed with a wildcard label (`*.`). The wildcard \n + \tlabel must appear by itself as the first label. \n Hostname + can be \"precise\" which is a domain name without the terminating + dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", + which is a domain name prefixed with a single wildcard label (e.g. + `*.example.com`). \n Note that as per RFC1035 and RFC1123, a *label* + must consist of lower case alphanumeric characters or '-', and + must start and end with an alphanumeric character. No other punctuation + is allowed." maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -2310,8 +2318,8 @@ spec: if all conditions are satisfied. \n For example, the match below will match a HTTP request only if its path starts with `/foo` AND it contains the `version: v1` header: \n - ``` match: path: value: \"/foo\" headers: - name: - \"version\" value \"v1\" ```" + “` match: \n \tpath: \t value: \"/foo\" \theaders: \t- + name: \"version\" \t value \"v1\" \n “`" properties: headers: description: Headers specifies HTTP request header matchers. diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha2/apis_client.go b/pkg/client/clientset/versioned/typed/apis/v1alpha2/apis_client.go index abc0b33e41..8a4bd69b43 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha2/apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/apis_client.go @@ -28,6 +28,7 @@ import ( type GatewayV1alpha2Interface interface { RESTClient() rest.Interface + GRPCRoutesGetter GatewaysGetter GatewayClassesGetter HTTPRoutesGetter @@ -43,6 +44,10 @@ type GatewayV1alpha2Client struct { restClient rest.Interface } +func (c *GatewayV1alpha2Client) GRPCRoutes(namespace string) GRPCRouteInterface { + return newGRPCRoutes(c, namespace) +} + func (c *GatewayV1alpha2Client) Gateways(namespace string) GatewayInterface { return newGateways(c, namespace) } diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_apis_client.go b/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_apis_client.go index f7aa51c902..043ac6f4db 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_apis_client.go @@ -28,6 +28,10 @@ type FakeGatewayV1alpha2 struct { *testing.Fake } +func (c *FakeGatewayV1alpha2) GRPCRoutes(namespace string) v1alpha2.GRPCRouteInterface { + return &FakeGRPCRoutes{c, namespace} +} + func (c *FakeGatewayV1alpha2) Gateways(namespace string) v1alpha2.GatewayInterface { return &FakeGateways{c, namespace} } diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_grpcroute.go b/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_grpcroute.go new file mode 100644 index 0000000000..33650a5c58 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_grpcroute.go @@ -0,0 +1,142 @@ +/* +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" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" +) + +// FakeGRPCRoutes implements GRPCRouteInterface +type FakeGRPCRoutes struct { + Fake *FakeGatewayV1alpha2 + ns string +} + +var grpcroutesResource = schema.GroupVersionResource{Group: "gateway.networking.k8s.io", Version: "v1alpha2", Resource: "grpcroutes"} + +var grpcroutesKind = schema.GroupVersionKind{Group: "gateway.networking.k8s.io", Version: "v1alpha2", Kind: "GRPCRoute"} + +// Get takes name of the gRPCRoute, and returns the corresponding gRPCRoute object, and an error if there is any. +func (c *FakeGRPCRoutes) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.GRPCRoute, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(grpcroutesResource, c.ns, name), &v1alpha2.GRPCRoute{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.GRPCRoute), err +} + +// List takes label and field selectors, and returns the list of GRPCRoutes that match those selectors. +func (c *FakeGRPCRoutes) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.GRPCRouteList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(grpcroutesResource, grpcroutesKind, c.ns, opts), &v1alpha2.GRPCRouteList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha2.GRPCRouteList{ListMeta: obj.(*v1alpha2.GRPCRouteList).ListMeta} + for _, item := range obj.(*v1alpha2.GRPCRouteList).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 gRPCRoutes. +func (c *FakeGRPCRoutes) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(grpcroutesResource, c.ns, opts)) + +} + +// Create takes the representation of a gRPCRoute and creates it. Returns the server's representation of the gRPCRoute, and an error, if there is any. +func (c *FakeGRPCRoutes) Create(ctx context.Context, gRPCRoute *v1alpha2.GRPCRoute, opts v1.CreateOptions) (result *v1alpha2.GRPCRoute, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(grpcroutesResource, c.ns, gRPCRoute), &v1alpha2.GRPCRoute{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.GRPCRoute), err +} + +// Update takes the representation of a gRPCRoute and updates it. Returns the server's representation of the gRPCRoute, and an error, if there is any. +func (c *FakeGRPCRoutes) Update(ctx context.Context, gRPCRoute *v1alpha2.GRPCRoute, opts v1.UpdateOptions) (result *v1alpha2.GRPCRoute, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(grpcroutesResource, c.ns, gRPCRoute), &v1alpha2.GRPCRoute{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.GRPCRoute), 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 *FakeGRPCRoutes) UpdateStatus(ctx context.Context, gRPCRoute *v1alpha2.GRPCRoute, opts v1.UpdateOptions) (*v1alpha2.GRPCRoute, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(grpcroutesResource, "status", c.ns, gRPCRoute), &v1alpha2.GRPCRoute{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.GRPCRoute), err +} + +// Delete takes name of the gRPCRoute and deletes it. Returns an error if one occurs. +func (c *FakeGRPCRoutes) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(grpcroutesResource, c.ns, name, opts), &v1alpha2.GRPCRoute{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeGRPCRoutes) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(grpcroutesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha2.GRPCRouteList{}) + return err +} + +// Patch applies the patch and returns the patched gRPCRoute. +func (c *FakeGRPCRoutes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.GRPCRoute, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(grpcroutesResource, c.ns, name, pt, data, subresources...), &v1alpha2.GRPCRoute{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.GRPCRoute), err +} diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha2/generated_expansion.go b/pkg/client/clientset/versioned/typed/apis/v1alpha2/generated_expansion.go index aec66839b3..fecf4d2219 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha2/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/generated_expansion.go @@ -18,6 +18,8 @@ limitations under the License. package v1alpha2 +type GRPCRouteExpansion interface{} + type GatewayExpansion interface{} type GatewayClassExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha2/grpcroute.go b/pkg/client/clientset/versioned/typed/apis/v1alpha2/grpcroute.go new file mode 100644 index 0000000000..42861ba703 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/grpcroute.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 v1alpha2 + +import ( + "context" + "time" + + v1 "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" + v1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + scheme "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/scheme" +) + +// GRPCRoutesGetter has a method to return a GRPCRouteInterface. +// A group's client should implement this interface. +type GRPCRoutesGetter interface { + GRPCRoutes(namespace string) GRPCRouteInterface +} + +// GRPCRouteInterface has methods to work with GRPCRoute resources. +type GRPCRouteInterface interface { + Create(ctx context.Context, gRPCRoute *v1alpha2.GRPCRoute, opts v1.CreateOptions) (*v1alpha2.GRPCRoute, error) + Update(ctx context.Context, gRPCRoute *v1alpha2.GRPCRoute, opts v1.UpdateOptions) (*v1alpha2.GRPCRoute, error) + UpdateStatus(ctx context.Context, gRPCRoute *v1alpha2.GRPCRoute, opts v1.UpdateOptions) (*v1alpha2.GRPCRoute, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha2.GRPCRoute, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha2.GRPCRouteList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.GRPCRoute, err error) + GRPCRouteExpansion +} + +// gRPCRoutes implements GRPCRouteInterface +type gRPCRoutes struct { + client rest.Interface + ns string +} + +// newGRPCRoutes returns a GRPCRoutes +func newGRPCRoutes(c *GatewayV1alpha2Client, namespace string) *gRPCRoutes { + return &gRPCRoutes{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the gRPCRoute, and returns the corresponding gRPCRoute object, and an error if there is any. +func (c *gRPCRoutes) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.GRPCRoute, err error) { + result = &v1alpha2.GRPCRoute{} + err = c.client.Get(). + Namespace(c.ns). + Resource("grpcroutes"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of GRPCRoutes that match those selectors. +func (c *gRPCRoutes) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.GRPCRouteList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha2.GRPCRouteList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("grpcroutes"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested gRPCRoutes. +func (c *gRPCRoutes) Watch(ctx context.Context, opts v1.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("grpcroutes"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a gRPCRoute and creates it. Returns the server's representation of the gRPCRoute, and an error, if there is any. +func (c *gRPCRoutes) Create(ctx context.Context, gRPCRoute *v1alpha2.GRPCRoute, opts v1.CreateOptions) (result *v1alpha2.GRPCRoute, err error) { + result = &v1alpha2.GRPCRoute{} + err = c.client.Post(). + Namespace(c.ns). + Resource("grpcroutes"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(gRPCRoute). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a gRPCRoute and updates it. Returns the server's representation of the gRPCRoute, and an error, if there is any. +func (c *gRPCRoutes) Update(ctx context.Context, gRPCRoute *v1alpha2.GRPCRoute, opts v1.UpdateOptions) (result *v1alpha2.GRPCRoute, err error) { + result = &v1alpha2.GRPCRoute{} + err = c.client.Put(). + Namespace(c.ns). + Resource("grpcroutes"). + Name(gRPCRoute.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(gRPCRoute). + 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 *gRPCRoutes) UpdateStatus(ctx context.Context, gRPCRoute *v1alpha2.GRPCRoute, opts v1.UpdateOptions) (result *v1alpha2.GRPCRoute, err error) { + result = &v1alpha2.GRPCRoute{} + err = c.client.Put(). + Namespace(c.ns). + Resource("grpcroutes"). + Name(gRPCRoute.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(gRPCRoute). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the gRPCRoute and deletes it. Returns an error if one occurs. +func (c *gRPCRoutes) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("grpcroutes"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *gRPCRoutes) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.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("grpcroutes"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched gRPCRoute. +func (c *gRPCRoutes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.GRPCRoute, err error) { + result = &v1alpha2.GRPCRoute{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("grpcroutes"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/informers/externalversions/apis/v1alpha2/grpcroute.go b/pkg/client/informers/externalversions/apis/v1alpha2/grpcroute.go new file mode 100644 index 0000000000..d7360bdb31 --- /dev/null +++ b/pkg/client/informers/externalversions/apis/v1alpha2/grpcroute.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 v1alpha2 + +import ( + "context" + time "time" + + v1 "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" + apisv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + versioned "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned" + internalinterfaces "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/internalinterfaces" + v1alpha2 "sigs.k8s.io/gateway-api/pkg/client/listers/apis/v1alpha2" +) + +// GRPCRouteInformer provides access to a shared informer and lister for +// GRPCRoutes. +type GRPCRouteInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha2.GRPCRouteLister +} + +type gRPCRouteInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewGRPCRouteInformer constructs a new informer for GRPCRoute 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 NewGRPCRouteInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredGRPCRouteInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredGRPCRouteInformer constructs a new informer for GRPCRoute 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 NewFilteredGRPCRouteInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().GRPCRoutes(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().GRPCRoutes(namespace).Watch(context.TODO(), options) + }, + }, + &apisv1alpha2.GRPCRoute{}, + resyncPeriod, + indexers, + ) +} + +func (f *gRPCRouteInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredGRPCRouteInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *gRPCRouteInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apisv1alpha2.GRPCRoute{}, f.defaultInformer) +} + +func (f *gRPCRouteInformer) Lister() v1alpha2.GRPCRouteLister { + return v1alpha2.NewGRPCRouteLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/apis/v1alpha2/interface.go b/pkg/client/informers/externalversions/apis/v1alpha2/interface.go index 4f900cdfa2..34fd1a7ce3 100644 --- a/pkg/client/informers/externalversions/apis/v1alpha2/interface.go +++ b/pkg/client/informers/externalversions/apis/v1alpha2/interface.go @@ -24,6 +24,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // GRPCRoutes returns a GRPCRouteInformer. + GRPCRoutes() GRPCRouteInformer // Gateways returns a GatewayInformer. Gateways() GatewayInformer // GatewayClasses returns a GatewayClassInformer. @@ -53,6 +55,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// GRPCRoutes returns a GRPCRouteInformer. +func (v *version) GRPCRoutes() GRPCRouteInformer { + return &gRPCRouteInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // Gateways returns a GatewayInformer. func (v *version) Gateways() GatewayInformer { return &gatewayInformer{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 921963ee8a..9d7c0c34e3 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -54,6 +54,8 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=gateway.networking.k8s.io, Version=v1alpha2 + case v1alpha2.SchemeGroupVersion.WithResource("grpcroutes"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1alpha2().GRPCRoutes().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("gateways"): return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1alpha2().Gateways().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("gatewayclasses"): diff --git a/pkg/client/listers/apis/v1alpha2/expansion_generated.go b/pkg/client/listers/apis/v1alpha2/expansion_generated.go index bb43c225e1..2a6573d2af 100644 --- a/pkg/client/listers/apis/v1alpha2/expansion_generated.go +++ b/pkg/client/listers/apis/v1alpha2/expansion_generated.go @@ -18,6 +18,14 @@ limitations under the License. package v1alpha2 +// GRPCRouteListerExpansion allows custom methods to be added to +// GRPCRouteLister. +type GRPCRouteListerExpansion interface{} + +// GRPCRouteNamespaceListerExpansion allows custom methods to be added to +// GRPCRouteNamespaceLister. +type GRPCRouteNamespaceListerExpansion interface{} + // GatewayListerExpansion allows custom methods to be added to // GatewayLister. type GatewayListerExpansion interface{} diff --git a/pkg/client/listers/apis/v1alpha2/grpcroute.go b/pkg/client/listers/apis/v1alpha2/grpcroute.go new file mode 100644 index 0000000000..822cddba97 --- /dev/null +++ b/pkg/client/listers/apis/v1alpha2/grpcroute.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 v1alpha2 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" +) + +// GRPCRouteLister helps list GRPCRoutes. +// All objects returned here must be treated as read-only. +type GRPCRouteLister interface { + // List lists all GRPCRoutes in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha2.GRPCRoute, err error) + // GRPCRoutes returns an object that can list and get GRPCRoutes. + GRPCRoutes(namespace string) GRPCRouteNamespaceLister + GRPCRouteListerExpansion +} + +// gRPCRouteLister implements the GRPCRouteLister interface. +type gRPCRouteLister struct { + indexer cache.Indexer +} + +// NewGRPCRouteLister returns a new GRPCRouteLister. +func NewGRPCRouteLister(indexer cache.Indexer) GRPCRouteLister { + return &gRPCRouteLister{indexer: indexer} +} + +// List lists all GRPCRoutes in the indexer. +func (s *gRPCRouteLister) List(selector labels.Selector) (ret []*v1alpha2.GRPCRoute, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.GRPCRoute)) + }) + return ret, err +} + +// GRPCRoutes returns an object that can list and get GRPCRoutes. +func (s *gRPCRouteLister) GRPCRoutes(namespace string) GRPCRouteNamespaceLister { + return gRPCRouteNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// GRPCRouteNamespaceLister helps list and get GRPCRoutes. +// All objects returned here must be treated as read-only. +type GRPCRouteNamespaceLister interface { + // List lists all GRPCRoutes in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha2.GRPCRoute, err error) + // Get retrieves the GRPCRoute from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha2.GRPCRoute, error) + GRPCRouteNamespaceListerExpansion +} + +// gRPCRouteNamespaceLister implements the GRPCRouteNamespaceLister +// interface. +type gRPCRouteNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all GRPCRoutes in the indexer for a given namespace. +func (s gRPCRouteNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.GRPCRoute, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.GRPCRoute)) + }) + return ret, err +} + +// Get retrieves the GRPCRoute from the indexer for a given namespace and name. +func (s gRPCRouteNamespaceLister) Get(name string) (*v1alpha2.GRPCRoute, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha2.Resource("grpcroute"), name) + } + return obj.(*v1alpha2.GRPCRoute), nil +}