diff --git a/.gitignore b/.gitignore index 0d1a0014a7..a8a804e1fa 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,4 @@ admission /cache .venv/ +release/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b9adba306..9828e54778 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Table of Contents +- [v0.4.3](#v043) +- [v0.4.2](#v042) +- [v0.4.1](#v041) - [v0.4.0](#v040) - [v0.4.0-rc2](#v040-rc2) - [v0.4.0-rc1](#v040-rc1) @@ -11,6 +14,45 @@ - [v0.1.0-rc2](#v010-rc2) - [v0.1.0-rc1](#v010-rc1) +## v0.4.3 + +API version: v1alpha2 + +This release includes improvements to our webhook, including: + +* Migrating kube-webhook-certgen to k8s.gcr.io/ingress-nginx:v1.1.1. + [#1126](https://github.com/kubernetes-sigs/gateway-api/pull/1126) +* New validation to ensure that a HTTPRouterFilter Type matches its value + [#1071](https://github.com/kubernetes-sigs/gateway-api/pull/1071) +* A fix to ensure that Path match validation actually works + [#1071](https://github.com/kubernetes-sigs/gateway-api/pull/1071) + +## v0.4.2 + +API version: v1alpha2 + +This release is intended to verify our webhook image tagging process. + +### Bug Fixes + +* Update image generation process with more consistent naming + [#1034](https://github.com/kubernetes-sigs/gateway-api/pull/1034) + +## v0.4.1 + +API version: v1alpha2 + +This release contains minor bug fixes for v1alpha2. + +### Bug Fixes + +* ControllerName now prints correctly in kubectl output for GatewayClass + [#909](https://github.com/kubernetes-sigs/gateway-api/pull/909) +* Namespace can no longer be left unspecified in ReferencePolicy + [#964](https://github.com/kubernetes-sigs/gateway-api/pull/964) +* Wildcard characters can no longer be used in redirect Hostname values + [#956](https://github.com/kubernetes-sigs/gateway-api/pull/956) + ## v0.4.0 API version: v1alpha2 diff --git a/Dockerfile b/Dockerfile index ba0c03b5ca..eaa859a9b1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM golang:1.17 AS build-env +FROM golang:1.18 AS build-env RUN mkdir -p /go/src/sig.k8s.io/gateway-api WORKDIR /go/src/sig.k8s.io/gateway-api COPY . . diff --git a/Makefile b/Makefile index 9af35ba23f..6394e82e6f 100644 --- a/Makefile +++ b/Makefile @@ -49,13 +49,28 @@ TOP := $(dir $(firstword $(MAKEFILE_LIST))) # ROOT is the root of the mkdocs tree. ROOT := $(abspath $(TOP)) +# Command-line flags passed to "go test" for the conformance +# test. These are passed after the "-args" flag. +CONFORMANCE_FLAGS ?= + all: generate vet fmt verify test # Run generators for protos, Deepcopy funcs, CRDs, and docs. .PHONY: generate -generate: +generate: update-codegen update-webhook-yaml + +.PHONY: update-codegen +update-codegen: hack/update-codegen.sh +.PHONY: update-webhook-yaml +update-webhook-yaml: + hack/update-webhook-yaml.sh + +.PHONY: build-install-yaml +build-install-yaml: + hack/build-install-yaml.sh + # Run go fmt against code fmt: go fmt ./... @@ -71,7 +86,7 @@ test: # Run conformance tests against controller implementation .PHONY: conformance conformance: - go test -v ./conformance/... + go test -v ./conformance/... -args ${CONFORMANCE_FLAGS} # Install CRD's and example resources to a pre-existing cluster. .PHONY: install diff --git a/README.md b/README.md index 3a4cf7b5c7..8f8df6a609 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ the specification and Custom Resource Definitions (CRDs). ## Status -The latest supported version is v1alpha2 as released by the [v0.4.2 -release](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v0.4.2) of +The latest supported version is v1alpha2 as released by the [v0.4.3 +release](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v0.4.3) of this project. This version of the API is expected to graduate to beta in the future with relatively minimal changes. diff --git a/RELEASE.md b/RELEASE.md index b2d6ed9f2d..5896fa3cbd 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -19,9 +19,22 @@ documentation]. - Write the [changelog](CHANGELOG.md) with user-visible API changes. This must go through the regular PR review process and get merged into the `master` branch. Approval of the PR indicates community consensus for a new release. -- Once the above PR is merged, the author must publish a new Git tag. This can - be done using the `git` CLI or Github's [release][release] - page. This step can be performed only by [Gateway API maintainers][gateway-api-team]. + +The following steps must be done by one of the [Gateway API maintainers][gateway-api-team]: + +For a major or minor release: +- Cut a `release-major.minor` branch that we can tag things in as needed. +For all releases: +- Check out the `release-major.minor` branch locally +- Update `pkg/generator/main.go` with the new semver tag and any updates to the API review URL. +- Run the following commnand `BASE_REF=vmajor.minor.patch make generate` which will update generated docs + and webhook with the correct version info. Note that the YAMLs will not work until the tag is actually + published in the next step. +- Publish a new Git tag. This can be done using the `git` CLI or Github's [release][release] + page. +- Run the `make build-install-yaml` command which will generate + install files in the `release/` directory and attach these files to + the Github release. [release]: https://gateway-api.sigs.k8s.io/references/releases/ [gateway-api-team]: https://github.com/kubernetes/org/blob/master/config/kubernetes-sigs/sig-network/teams.yaml diff --git a/apis/v1alpha2/gateway_types.go b/apis/v1alpha2/gateway_types.go index 10ee4c67ea..ecf8ff10c7 100644 --- a/apis/v1alpha2/gateway_types.go +++ b/apis/v1alpha2/gateway_types.go @@ -135,7 +135,7 @@ type GatewaySpec struct { // it assigns to the Gateway and add a corresponding entry in // GatewayStatus.Addresses. // - // Support: Core + // Support: Extended // // +optional // +kubebuilder:validation:MaxItems=16 @@ -172,6 +172,10 @@ type Listener struct { // accepted. For more information, refer to the Route specific Hostnames // documentation. // + // Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + // as a suffix match. That means that a match for `*.example.com` would match + // both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + // // Support: Core // // +optional @@ -310,8 +314,8 @@ type GatewayTLSConfig struct { // a Listener, but this behavior is implementation-specific. // // References to a resource in different namespace are invalid UNLESS there - // is a ReferencePolicy in the target namespace that allows the certificate - // to be attached. If a ReferencePolicy does not allow this reference, the + // is a ReferenceGrant in the target namespace that allows the certificate + // to be attached. If a ReferenceGrant does not allow this reference, the // "ResolvedRefs" condition MUST be set to False for this listener with the // "InvalidCertificateRef" reason. // @@ -321,13 +325,13 @@ type GatewayTLSConfig struct { // CertificateRefs can reference to standard Kubernetes resources, i.e. // Secret, or implementation-specific custom resources. // - // Support: Core - A single reference to a Kubernetes Secret + // Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls // // Support: Implementation-specific (More than one reference or other resource types) // // +optional // +kubebuilder:validation:MaxItems=64 - CertificateRefs []*SecretObjectReference `json:"certificateRefs,omitempty"` + CertificateRefs []SecretObjectReference `json:"certificateRefs,omitempty"` // Options are a list of key/value pairs to enable extended TLS // configuration for each implementation. For example, configuring the @@ -641,7 +645,6 @@ const ( // // * "HostnameConflict" // * "ProtocolConflict" - // * "RouteConflict" // // Possible reasons for this condition to be False are: // @@ -663,13 +666,6 @@ const ( // number, but have conflicting protocol specifications. ListenerReasonProtocolConflict ListenerConditionReason = "ProtocolConflict" - // This reason is used with the "Conflicted" condition when the route - // resources selected for this Listener conflict with other - // specified properties of the Listener (e.g. Protocol). - // For example, a Listener that specifies "UDP" as the protocol - // but a route selector that resolves "TCPRoute" objects. - ListenerReasonRouteConflict ListenerConditionReason = "RouteConflict" - // This reason is used with the "Conflicted" condition when the condition // is False. ListenerReasonNoConflicts ListenerConditionReason = "NoConflicts" @@ -689,7 +685,6 @@ const ( // Possible reasons for this condition to be true are: // // * "PortUnavailable" - // * "UnsupportedExtension" // * "UnsupportedProtocol" // * "UnsupportedAddress" // @@ -710,12 +705,6 @@ const ( // * The port is not supported by the implementation. ListenerReasonPortUnavailable ListenerConditionReason = "PortUnavailable" - // This reason is used with the "Detached" condition when the - // controller detects that an implementation-specific Listener - // extension is being requested, but is not able to support - // the extension. - ListenerReasonUnsupportedExtension ListenerConditionReason = "UnsupportedExtension" - // This reason is used with the "Detached" condition when the // Listener could not be attached to be Gateway because its // protocol type is not supported. @@ -769,7 +758,7 @@ const ( // This reason is used with the "ResolvedRefs" condition when // one of the Listener's Routes has a BackendRef to an object in // another namespace, where the object in the other namespace does - // not have a ReferencePolicy explicitly allowing the reference. + // not have a ReferenceGrant explicitly allowing the reference. ListenerReasonRefNotPermitted ListenerConditionReason = "RefNotPermitted" ) diff --git a/apis/v1alpha2/gatewayclass_types.go b/apis/v1alpha2/gatewayclass_types.go index 699bc78c8a..e73b6b36dd 100644 --- a/apis/v1alpha2/gatewayclass_types.go +++ b/apis/v1alpha2/gatewayclass_types.go @@ -27,6 +27,7 @@ import ( // +kubebuilder:subresource:status // +kubebuilder:storageversion // +kubebuilder:printcolumn:name="Controller",type=string,JSONPath=`.spec.controllerName` +// +kubebuilder:printcolumn:name="Accepted",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].status` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` // +kubebuilder:printcolumn:name="Description",type=string,JSONPath=`.spec.description`,priority=1 diff --git a/apis/v1alpha2/httproute_types.go b/apis/v1alpha2/httproute_types.go index 5edaa18e46..865fb93344 100644 --- a/apis/v1alpha2/httproute_types.go +++ b/apis/v1alpha2/httproute_types.go @@ -74,8 +74,13 @@ type HTTPRouteSpec struct { // * A Listener with `*.example.com` as the hostname matches HTTPRoutes // that have either not specified any hostnames or have specified at least // one hostname that matches the Listener hostname. For example, - // `test.example.com` and `*.example.com` would both match. On the other - // hand, `example.com` and `test.example.net` would not match. + // `*.example.com`, `test.example.com`, and `foo.test.example.com` would + // all match. On the other hand, `example.com` and `test.example.net` would + // not match. + // + // Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + // as a suffix match. That means that a match for `*.example.com` would match + // both `test.example.com`, and `foo.test.example.com`, but not `example.com`. // // If both the Listener and HTTPRoute have specified hostnames, any // HTTPRoute hostnames that do not match the Listener hostname MUST be @@ -158,6 +163,9 @@ type HTTPRouteRule struct { // matching precedence MUST be granted to the first matching rule meeting // the above criteria. // + // When no rules matching a request have been successfully attached to the + // parent a request is coming from, a HTTP 404 status code MUST be returned. + // // +optional // +kubebuilder:validation:MaxItems=8 // +kubebuilder:default={{path:{ type: "PathPrefix", value: "/"}}} @@ -187,13 +195,25 @@ type HTTPRouteRule struct { // BackendRefs defines the backend(s) where matching requests should be // sent. - - // If unspecified or invalid (refers to a non-existent resource or a Service - // with no endpoints), the rule performs no forwarding. If there are also no - // filters specified that would result in a response being sent, a HTTP 503 - // status code is returned. 503 responses must be sent so that the overall - // weight is respected; if an invalid backend is requested to have 80% of - // requests, then 80% of requests must get a 503 instead. + // + // A 404 status code 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, 404 status codes MUST be returned for + // requests that would have otherwise been routed to an invalid backend. If + // multiple backends are specified, and some are invalid, the proportion of + // requests that would otherwise have been routed to an invalid backend + // MUST receive a 404 status code. + // + // When a BackendRef refers to a Service that has no ready endpoints, it is + // recommended to return a 503 status code. // // Support: Core for Kubernetes Service // Support: Custom for any other resource @@ -229,7 +249,7 @@ const ( // path element refers to the list of labels in the path split by // the `/` separator. When specified, a trailing `/` is ignored. // - // For example. the paths `/abc`, `/abc/`, and `/abc/def` would all match + // For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match // the prefix `/abc`, but the path `/abcd` would not. // // "PathPrefix" is semantically equivalent to the "Prefix" path type in the @@ -684,13 +704,13 @@ type HTTPRequestHeaderFilter struct { Remove []string `json:"remove,omitempty"` } -// HTTPPathModifierType defines the type of path redirect. +// HTTPPathModifierType defines the type of path redirect or rewrite. type HTTPPathModifierType string const ( - // This type of modifier indicates that the complete path will be replaced - // by the path redirect value. - AbsoluteHTTPPathModifier HTTPPathModifierType = "Absolute" + // This type of modifier indicates that the full path will be replaced + // by the specified value. + FullPathHTTPPathModifier HTTPPathModifierType = "ReplaceFullPath" // This type of modifier indicates that any prefix path matches will be // replaced by the substitution value. For example, a path with a prefix @@ -702,24 +722,33 @@ const ( // HTTPPathModifier defines configuration for path modifiers. // type HTTPPathModifier struct { - // Type defines the type of path modifier. + // Type defines the type of path modifier. Additional types may be + // added in a future release of the API. // // - // +kubebuilder:validation:Enum=Absolute;ReplacePrefixMatch + // +kubebuilder:validation:Enum=ReplaceFullPath;ReplacePrefixMatch Type HTTPPathModifierType `json:"type"` - // Substitution defines the HTTP path value to substitute. An empty value - // ("") indicates that the portion of the path to be changed should be - // removed from the resulting path. For example, a request to "/foo/bar" - // with a prefix match of "/foo" would be modified to "/bar". + // ReplaceFullPath specifies the value with which to replace the full path + // of a request during a rewrite or redirect. // // // +kubebuilder:validation:MaxLength=1024 - Substitution string `json:"substitution"` + // +optional + ReplaceFullPath *string `json:"replaceFullPath,omitempty"` + + // ReplacePrefixMatch specifies the value with which to replace the prefix + // match of a request during a rewrite or redirect. For example, a request + // to "/foo/bar" with a prefix match of "/foo" would be modified to "/bar". + // + // + // +kubebuilder:validation:MaxLength=1024 + // +optional + ReplacePrefixMatch *string `json:"replacePrefixMatch,omitempty"` } // HTTPRequestRedirect defines a filter that redirects a request. This filter -// MUST not be used on the same Route rule as a HTTPURLRewrite filter. +// MUST NOT be used on the same Route rule as a HTTPURLRewrite filter. type HTTPRequestRedirectFilter struct { // Scheme is the scheme to be used in the value of the `Location` // header in the response. @@ -771,7 +800,7 @@ type HTTPRequestRedirectFilter struct { // HTTPURLRewriteFilter defines a filter that modifies a request during // forwarding. At most one of these filters may be used on a Route rule. This -// may not be used on the same Route rule as a HTTPRequestRedirect filter. +// MUST NOT be used on the same Route rule as a HTTPRequestRedirect filter. // // // Support: Extended @@ -783,7 +812,7 @@ type HTTPURLRewriteFilter struct { // // // +optional - Hostname *Hostname `json:"hostname,omitempty"` + Hostname *PreciseHostname `json:"hostname,omitempty"` // Path defines a path rewrite. // @@ -804,7 +833,7 @@ type HTTPRequestMirrorFilter struct { // this backend in the underlying implementation. // // If there is a cross-namespace reference to an *existing* object - // that is not allowed by a ReferencePolicy, the controller must ensure the + // 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. @@ -827,7 +856,7 @@ type HTTPBackendRef struct { // 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 + // that is not covered 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. diff --git a/apis/v1alpha2/object_reference_types.go b/apis/v1alpha2/object_reference_types.go index 12730b9ed6..8365168106 100644 --- a/apis/v1alpha2/object_reference_types.go +++ b/apis/v1alpha2/object_reference_types.go @@ -65,9 +65,9 @@ type SecretObjectReference struct { // Namespace is the namespace of the backend. When unspecified, the local // namespace is inferred. // - // Note that when a namespace is specified, a ReferencePolicy object + // Note that when a namespace is specified, a ReferenceGrant object // is required in the referent namespace to allow that namespace's - // owner to accept the reference. See the ReferencePolicy documentation + // owner to accept the reference. See the ReferenceGrant documentation // for details. // // Support: Core @@ -80,9 +80,9 @@ type SecretObjectReference struct { // specific to BackendRef. It includes a few additional fields and features // than a regular ObjectReference. // -// Note that when a namespace is specified, a ReferencePolicy object +// Note that when a namespace is specified, a ReferenceGrant object // is required in the referent namespace to allow that namespace's -// owner to accept the reference. See the ReferencePolicy documentation +// owner to accept the reference. See the ReferenceGrant documentation // for details. // // The API object must be valid in the cluster; the Group and Kind must @@ -100,6 +100,7 @@ type BackendObjectReference struct { Group *Group `json:"group,omitempty"` // Kind is kind of the referent. For example "HTTPRoute" or "Service". + // Defaults to "Service" when not specified. // // +optional // +kubebuilder:default=Service @@ -111,9 +112,9 @@ type BackendObjectReference struct { // Namespace is the namespace of the backend. When unspecified, the local // namespace is inferred. // - // Note that when a namespace is specified, a ReferencePolicy object + // Note that when a namespace is specified, a ReferenceGrant object // is required in the referent namespace to allow that namespace's - // owner to accept the reference. See the ReferencePolicy documentation + // owner to accept the reference. See the ReferenceGrant documentation // for details. // // Support: Core diff --git a/apis/v1alpha2/referencepolicy_types.go b/apis/v1alpha2/referencepolicy_types.go index 76f759ee3f..0aea80b8f0 100644 --- a/apis/v1alpha2/referencepolicy_types.go +++ b/apis/v1alpha2/referencepolicy_types.go @@ -24,25 +24,25 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // +kubebuilder:storageversion // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` -// ReferencePolicy identifies kinds of resources in other namespaces that are +// ReferenceGrant identifies kinds of resources in other namespaces that are // trusted to reference the specified kinds of resources in the same namespace // as the policy. // -// Each ReferencePolicy can be used to represent a unique trust relationship. +// Each ReferenceGrant can be used to represent a unique trust relationship. // Additional Reference Policies can be used to add to the set of trusted // sources of inbound references for the namespace they are defined within. // // All cross-namespace references in Gateway API (with the exception of cross-namespace -// Gateway-route attachment) require a ReferencePolicy. +// Gateway-route attachment) require a ReferenceGrant. // // Support: Core // -type ReferencePolicy struct { +type ReferenceGrant struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - // Spec defines the desired state of ReferencePolicy. - Spec ReferencePolicySpec `json:"spec,omitempty"` + // Spec defines the desired state of ReferenceGrant. + Spec ReferenceGrantSpec `json:"spec,omitempty"` // Note that `Status` sub-resource has been excluded at the // moment as it was difficult to work out the design. @@ -50,16 +50,16 @@ type ReferencePolicy struct { } // +kubebuilder:object:root=true -// ReferencePolicyList contains a list of ReferencePolicy. -type ReferencePolicyList struct { +// ReferenceGrantList contains a list of ReferenceGrant. +type ReferenceGrantList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` - Items []ReferencePolicy `json:"items"` + Items []ReferenceGrant `json:"items"` } -// ReferencePolicySpec identifies a cross namespace relationship that is trusted +// ReferenceGrantSpec identifies a cross namespace relationship that is trusted // for Gateway API. -type ReferencePolicySpec struct { +type ReferenceGrantSpec struct { // From describes the trusted namespaces and kinds that can reference the // resources described in "To". Each entry in this list must be considered // to be an additional place that references can be valid from, or to put @@ -69,7 +69,7 @@ type ReferencePolicySpec struct { // // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 - From []ReferencePolicyFrom `json:"from"` + From []ReferenceGrantFrom `json:"from"` // To describes the resources that may be referenced by the resources // described in "From". Each entry in this list must be considered to be an @@ -80,11 +80,11 @@ type ReferencePolicySpec struct { // // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 - To []ReferencePolicyTo `json:"to"` + To []ReferenceGrantTo `json:"to"` } -// ReferencePolicyFrom describes trusted namespaces and kinds. -type ReferencePolicyFrom struct { +// ReferenceGrantFrom describes trusted namespaces and kinds. +type ReferenceGrantFrom struct { // Group is the group of the referent. // When empty, the Kubernetes core API group is inferred. // @@ -107,9 +107,9 @@ type ReferencePolicyFrom struct { Namespace Namespace `json:"namespace"` } -// ReferencePolicyTo describes what Kinds are allowed as targets of the +// ReferenceGrantTo describes what Kinds are allowed as targets of the // references. -type ReferencePolicyTo struct { +type ReferenceGrantTo struct { // Group is the group of the referent. // When empty, the Kubernetes core API group is inferred. // diff --git a/apis/v1alpha2/shared_types.go b/apis/v1alpha2/shared_types.go index 99ff6cbc3e..8611096b1e 100644 --- a/apis/v1alpha2/shared_types.go +++ b/apis/v1alpha2/shared_types.go @@ -27,10 +27,6 @@ import ( // // The API object must be valid in the cluster; the Group and Kind must // be registered in the cluster for this reference to be valid. -// -// References to objects with invalid Group and Kind are not valid, and must -// be rejected by the implementation, with appropriate Conditions set -// on the containing object. type ParentReference struct { // Group is the group of the referent. // @@ -88,15 +84,15 @@ type ParentReference struct { SectionName *SectionName `json:"sectionName,omitempty"` // Port is the network port this Route targets. It can be interpreted - // differently based on the type of parent resource: + // differently based on the type of parent resource. // - // * Gateway: All listeners listening on the specified port that also - // support this kind of Route(and select this Route). It's not - // recommended to set `Port` unless the networking behaviors specified - // in a Route must apply to a specific port as opposed to a listener(s) - // whose port(s) may be changed. When both Port and SectionName are - // specified, the name and port of the selected listener must match both - // specified values. + // When the parent resource is a 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. // // Implementations MAY choose to support other parent resources. // Implementations supporting other types of parent resources MUST clearly @@ -154,9 +150,9 @@ type PortNumber int32 // BackendRef defines how a Route should forward a request to a Kubernetes // resource. // -// Note that when a namespace is specified, a ReferencePolicy object +// Note that when a namespace is specified, a ReferenceGrant object // is required in the referent namespace to allow that namespace's -// owner to accept the reference. See the ReferencePolicy documentation +// owner to accept the reference. See the ReferenceGrant documentation // for details. type BackendRef struct { // BackendObjectReference references a Kubernetes object. @@ -186,14 +182,65 @@ type BackendRef struct { // RouteConditionType is a type of condition for a route. type RouteConditionType string +// RouteConditionReason is a reason for a route condition. +type RouteConditionReason string + const ( // This condition indicates whether the route has been accepted or rejected // by a Gateway, and why. - ConditionRouteAccepted RouteConditionType = "Accepted" + // + // Possible reasons for this condition to be true are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "NotAllowedByListeners" + // * "NoMatchingListenerHostname" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + RouteConditionAccepted RouteConditionType = "Accepted" + + // This reason is used with the "Accepted" condition when the Route has been + // accepted by the Gateway. + RouteReasonAccepted RouteConditionReason = "Accepted" + + // This reason is used with the "Accepted" condition when the route has not + // been accepted by a Gateway because the Gateway has no Listener whose + // allowedRoutes criteria permit the route + RouteReasonNotAllowedByListeners RouteConditionReason = "NotAllowedByListeners" + + // This reason is used with the "Accepted" condition when the Gateway has no + // compatible Listeners whose Hostname matches the route + RouteReasonNoMatchingListenerHostname RouteConditionReason = "NoMatchingListenerHostname" // This condition indicates whether the controller was able to resolve all // the object references for the Route. - ConditionRouteResolvedRefs RouteConditionType = "ResolvedRefs" + // + // Possible reasons for this condition to be true are: + // + // * "ResolvedRefs" + // + // Possible reasons for this condition to be false are: + // + // * "RefNotPermitted" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + RouteConditionResolvedRefs RouteConditionType = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the condition + // is true. + RouteReasonResolvedRefs RouteConditionReason = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when + // one of the Listener's Routes has a BackendRef to an object in + // another namespace, where the object in the other namespace does + // not have a ReferenceGrant explicitly allowing the reference. + RouteReasonRefNotPermitted RouteConditionReason = "RefNotPermitted" ) // RouteParentStatus describes the status of a route with respect to an @@ -212,6 +259,10 @@ type RouteParentStatus struct { // The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are // valid Kubernetes names // (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + // + // Controllers MUST populate this field when writing status. Controllers should ensure that + // entries to status populated with their ControllerName are cleaned up when they are no + // longer necessary. ControllerName GatewayController `json:"controllerName"` // Conditions describes the status of the route with respect to the Gateway. @@ -283,13 +334,10 @@ type RouteStatus struct { // +kubebuilder:validation:Pattern=`^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` type Hostname string -// PreciseHostname is the fully qualified domain name of a network host. This matches -// the RFC 1123 definition of a hostname with 1 notable exception that +// PreciseHostname is the fully qualified domain name of a network host. This +// matches the RFC 1123 definition of a hostname with 1 notable exception that // numeric IP addresses are not allowed. // -// PreciseHostname can be "precise" which is a domain name without the terminating -// dot of a network host (e.g. "foo.example.com"). -// // Note that as per RFC1035 and RFC1123, a *label* must consist of lower case // alphanumeric characters or '-', and must start and end with an alphanumeric // character. No other punctuation is allowed. @@ -431,57 +479,6 @@ type AnnotationKey string // +kubebuilder:validation:MaxLength=4096 type AnnotationValue string -// AddressRouteMatches defines AddressMatch rules for inbound traffic according to -// source and/or destination address of a packet or connection. -type AddressRouteMatches struct { - // SourceAddresses indicates the originating (source) network - // addresses which are valid for routing traffic. - // - // Support: Extended - SourceAddresses []AddressMatch `json:"sourceAddresses"` - - // DestinationAddresses indicates the destination network addresses - // which are valid for routing traffic. - // - // Support: Extended - DestinationAddresses []AddressMatch `json:"destinationAddresses"` -} - -// AddressMatch defines matching rules for network addresses by type. -type AddressMatch struct { - // Type of the address, either IPAddress or NamedAddress. - // - // If NamedAddress is used this is a custom and specific value for each - // implementation to handle (and add validation for) according to their - // own needs. - // - // For IPAddress the implementor may expect either IPv4 or IPv6. - // - // Support: Core (IPAddress) - // Support: Custom (NamedAddress) - // - // +optional - // +kubebuilder:validation:Enum=IPAddress;NamedAddress - // +kubebuilder:default=IPAddress - Type *AddressType `json:"type,omitempty"` - - // Value of the address. The validity of the values will depend - // on the type and support by the controller. - // - // If implementations support proxy-protocol (see: - // https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) they - // must respect the connection metadata from proxy-protocol - // in the match logic implemented for these address values. - // - // Examples: `1.2.3.4`, `128::1`, `my-named-address`. - // - // Support: Core - // - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:MaxLength=253 - Value string `json:"value"` -} - // AddressType defines how a network address is represented as a text string. type AddressType string diff --git a/apis/v1alpha2/tcproute_types.go b/apis/v1alpha2/tcproute_types.go index 7cac3b160c..60d805787d 100644 --- a/apis/v1alpha2/tcproute_types.go +++ b/apis/v1alpha2/tcproute_types.go @@ -59,13 +59,6 @@ type TCPRouteStatus struct { // TCPRouteRule is the configuration for a given rule. type TCPRouteRule struct { - // Matches are rules for routing traffic to backends based on addresses. - // - // +optional - // +kubebuilder:validation:MaxItems=16 - // - Matches []AddressRouteMatches `json:"matches,omitempty"` - // BackendRefs defines the backend(s) where matching requests should be // sent. If unspecified or invalid (refers to a non-existent resource or a // Service with no endpoints), the underlying implementation MUST actively diff --git a/apis/v1alpha2/tlsroute_types.go b/apis/v1alpha2/tlsroute_types.go index e8f3faa7f1..6143b79c25 100644 --- a/apis/v1alpha2/tlsroute_types.go +++ b/apis/v1alpha2/tlsroute_types.go @@ -105,7 +105,7 @@ type TLSRouteRule struct { // a Service with no endpoints), the rule performs no forwarding; if no // filters are specified that would result in a response being sent, the // underlying implementation must actively reject request attempts to this - // backend, by rejecting the connection or returning a 503 status code. + // backend, by rejecting the connection or returning a 404 status code. // Request rejections must respect weight; if an invalid backend is // requested to have 80% of requests, then 80% of requests must be rejected // instead. diff --git a/apis/v1alpha2/udproute_types.go b/apis/v1alpha2/udproute_types.go index 99d7134568..361713afb2 100644 --- a/apis/v1alpha2/udproute_types.go +++ b/apis/v1alpha2/udproute_types.go @@ -59,13 +59,6 @@ type UDPRouteStatus struct { // UDPRouteRule is the configuration for a given rule. type UDPRouteRule struct { - // Matches add rules for filtering traffic to backends based on addresses. - // - // +optional - // +kubebuilder:validation:MaxItems=16 - // - Matches []AddressRouteMatches `json:"matches,omitempty"` - // BackendRefs defines the backend(s) where matching requests should be // sent. If unspecified or invalid (refers to a non-existent resource or a // Service with no endpoints), the underlying implementation MUST actively diff --git a/apis/v1alpha2/validation/httproute.go b/apis/v1alpha2/validation/httproute.go index 67101ba9ec..c892fbba7c 100644 --- a/apis/v1alpha2/validation/httproute.go +++ b/apis/v1alpha2/validation/httproute.go @@ -48,9 +48,9 @@ func ValidateHTTPRoute(route *gatewayv1a2.HTTPRoute) field.ErrorList { func validateHTTPRouteSpec(spec *gatewayv1a2.HTTPRouteSpec, path *field.Path) field.ErrorList { var errs field.ErrorList for i, rule := range spec.Rules { - errs = append(errs, validateHTTPRouteFilters(rule.Filters, path.Child("rules").Index(i))...) + errs = append(errs, validateHTTPRouteFilters(rule.Filters, rule.Matches, path.Child("rules").Index(i))...) for j, backendRef := range rule.BackendRefs { - errs = append(errs, validateHTTPRouteFilters(backendRef.Filters, path.Child("rules").Index(i).Child("backendsrefs").Index(j))...) + errs = append(errs, validateHTTPRouteFilters(backendRef.Filters, rule.Matches, path.Child("rules").Index(i).Child("backendsrefs").Index(j))...) } for j, m := range rule.Matches { if m.Path != nil { @@ -90,12 +90,18 @@ func validateHTTPRouteBackendServicePorts(rules []gatewayv1a2.HTTPRouteRule, pat // validateHTTPRouteFilters validates that a list of core and extended filters // is used at most once and that the filter type matches its value -func validateHTTPRouteFilters(filters []gatewayv1a2.HTTPRouteFilter, path *field.Path) field.ErrorList { +func validateHTTPRouteFilters(filters []gatewayv1a2.HTTPRouteFilter, matches []gatewayv1a2.HTTPRouteMatch, path *field.Path) field.ErrorList { var errs field.ErrorList counts := map[gatewayv1a2.HTTPRouteFilterType]int{} for i, filter := range filters { counts[filter.Type]++ + if filter.RequestRedirect != nil && filter.RequestRedirect.Path != nil { + errs = append(errs, validateHTTPPathModifier(*filter.RequestRedirect.Path, matches, path.Index(i).Child("requestRedirect", "path"))...) + } + if filter.URLRewrite != nil && filter.URLRewrite.Path != nil { + errs = append(errs, validateHTTPPathModifier(*filter.URLRewrite.Path, matches, path.Index(i).Child("urlRewrite", "path"))...) + } errs = append(errs, validateHTTPRouteFilterTypeMatchesValue(filter, path.Index(i))...) } // custom filters don't have any validation @@ -103,6 +109,10 @@ func validateHTTPRouteFilters(filters []gatewayv1a2.HTTPRouteFilter, path *field delete(counts, key) } + if counts[gatewayv1a2.HTTPRouteFilterRequestRedirect] > 0 && counts[gatewayv1a2.HTTPRouteFilterURLRewrite] > 0 { + errs = append(errs, field.Invalid(path.Child("filters"), gatewayv1a2.HTTPRouteFilterRequestRedirect, "Redirect and Rewrite filters cannot be defined in the same list of filters")) + } + for filterType, count := range counts { if count > 1 { errs = append(errs, field.Invalid(path.Child("filters"), filterType, "cannot be used multiple times in the same rule")) @@ -185,3 +195,40 @@ func validateHTTPRouteFilterTypeMatchesValue(filter gatewayv1a2.HTTPRouteFilter, } return errs } + +// validateHTTPPathModifier validates that only the expected fields are set in a +// path modifier. +func validateHTTPPathModifier(modifier gatewayv1a2.HTTPPathModifier, matches []gatewayv1a2.HTTPRouteMatch, path *field.Path) field.ErrorList { + var errs field.ErrorList + if modifier.ReplaceFullPath != nil && modifier.Type != gatewayv1a2.FullPathHTTPPathModifier { + errs = append(errs, field.Invalid(path, modifier.ReplaceFullPath, "must be nil if the HTTPRouteFilter.Type is not ReplaceFullPath")) + } + if modifier.ReplaceFullPath == nil && modifier.Type == gatewayv1a2.FullPathHTTPPathModifier { + errs = append(errs, field.Invalid(path, modifier.ReplaceFullPath, "must not be nil if the HTTPRouteFilter.Type is ReplaceFullPath")) + } + if modifier.ReplacePrefixMatch != nil && modifier.Type != gatewayv1a2.PrefixMatchHTTPPathModifier { + errs = append(errs, field.Invalid(path, modifier.ReplacePrefixMatch, "must be nil if the HTTPRouteFilter.Type is not ReplacePrefixMatch")) + } + if modifier.ReplacePrefixMatch == nil && modifier.Type == gatewayv1a2.PrefixMatchHTTPPathModifier { + errs = append(errs, field.Invalid(path, modifier.ReplacePrefixMatch, "must not be nil if the HTTPRouteFilter.Type is ReplacePrefixMatch")) + } + + if modifier.Type == gatewayv1a2.PrefixMatchHTTPPathModifier && modifier.ReplacePrefixMatch != nil { + if !hasExactlyOnePrefixMatch(matches) { + errs = append(errs, field.Invalid(path, modifier.ReplacePrefixMatch, "exactly one PathPrefix match must be specified to use this path modifier")) + } + } + return errs +} + +func hasExactlyOnePrefixMatch(matches []gatewayv1a2.HTTPRouteMatch) bool { + if len(matches) != 1 || matches[0].Path == nil { + return false + } + pathMatchType := matches[0].Path.Type + if *pathMatchType != gatewayv1a2.PathMatchPathPrefix { + return false + } + + return true +} diff --git a/apis/v1alpha2/validation/httproute_test.go b/apis/v1alpha2/validation/httproute_test.go index 770fba1872..ee2262325b 100644 --- a/apis/v1alpha2/validation/httproute_test.go +++ b/apis/v1alpha2/validation/httproute_test.go @@ -30,6 +30,8 @@ import ( func TestValidateHTTPRoute(t *testing.T) { testService := gatewayv1a2.ObjectName("test-service") specialService := gatewayv1a2.ObjectName("special-service") + pathPrefixMatchType := gatewayv1a2.PathMatchPathPrefix + tests := []struct { name string rules []gatewayv1a2.HTTPRouteRule @@ -293,6 +295,133 @@ func TestValidateHTTPRoute(t *testing.T) { }, }, }, + }, { + name: "valid redirect path modifier", + errCount: 0, + rules: []gatewayv1a2.HTTPRouteRule{ + { + Filters: []gatewayv1a2.HTTPRouteFilter{ + { + Type: gatewayv1a2.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1a2.HTTPRequestRedirectFilter{ + Path: &gatewayv1a2.HTTPPathModifier{ + Type: gatewayv1a2.FullPathHTTPPathModifier, + ReplaceFullPath: utilpointer.String("foo"), + }, + }, + }, + }, + }, + }, + }, { + name: "redirect path modifier with type mismatch", + errCount: 2, + rules: []gatewayv1a2.HTTPRouteRule{{ + Filters: []gatewayv1a2.HTTPRouteFilter{{ + Type: gatewayv1a2.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1a2.HTTPRequestRedirectFilter{ + Path: &gatewayv1a2.HTTPPathModifier{ + Type: gatewayv1a2.PrefixMatchHTTPPathModifier, + ReplaceFullPath: utilpointer.String("foo"), + }, + }, + }}, + }}, + }, { + name: "valid rewrite path modifier", + errCount: 0, + rules: []gatewayv1a2.HTTPRouteRule{{ + Matches: []gatewayv1a2.HTTPRouteMatch{{ + Path: &gatewayv1a2.HTTPPathMatch{ + Type: &pathPrefixMatchType, + Value: utilpointer.String("/bar"), + }, + }}, + Filters: []gatewayv1a2.HTTPRouteFilter{{ + Type: gatewayv1a2.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{ + Path: &gatewayv1a2.HTTPPathModifier{ + Type: gatewayv1a2.PrefixMatchHTTPPathModifier, + ReplacePrefixMatch: utilpointer.String("foo"), + }, + }, + }}, + }}, + }, { + name: "rewrite path modifier missing path match", + errCount: 1, + rules: []gatewayv1a2.HTTPRouteRule{{ + Filters: []gatewayv1a2.HTTPRouteFilter{{ + Type: gatewayv1a2.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{ + Path: &gatewayv1a2.HTTPPathModifier{ + Type: gatewayv1a2.PrefixMatchHTTPPathModifier, + ReplacePrefixMatch: utilpointer.String("foo"), + }, + }, + }}, + }}, + }, { + name: "rewrite path too many matches", + errCount: 1, + rules: []gatewayv1a2.HTTPRouteRule{{ + Matches: []gatewayv1a2.HTTPRouteMatch{{ + Path: &gatewayv1a2.HTTPPathMatch{ + Type: &pathPrefixMatchType, + Value: utilpointer.String("/foo"), + }, + }, { + Path: &gatewayv1a2.HTTPPathMatch{ + Type: &pathPrefixMatchType, + Value: utilpointer.String("/bar"), + }, + }}, + Filters: []gatewayv1a2.HTTPRouteFilter{{ + Type: gatewayv1a2.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{ + Path: &gatewayv1a2.HTTPPathModifier{ + Type: gatewayv1a2.PrefixMatchHTTPPathModifier, + ReplacePrefixMatch: utilpointer.String("foo"), + }, + }, + }}, + }}, + }, { + name: "redirect path modifier with type mismatch", + errCount: 2, + rules: []gatewayv1a2.HTTPRouteRule{{ + Filters: []gatewayv1a2.HTTPRouteFilter{{ + Type: gatewayv1a2.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{ + Path: &gatewayv1a2.HTTPPathModifier{ + Type: gatewayv1a2.FullPathHTTPPathModifier, + ReplacePrefixMatch: utilpointer.String("foo"), + }, + }, + }}, + }}, + }, { + name: "rewrite and redirect filters combined (invalid)", + errCount: 3, + rules: []gatewayv1a2.HTTPRouteRule{{ + Filters: []gatewayv1a2.HTTPRouteFilter{{ + Type: gatewayv1a2.HTTPRouteFilterURLRewrite, + URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{ + Path: &gatewayv1a2.HTTPPathModifier{ + Type: gatewayv1a2.PrefixMatchHTTPPathModifier, + ReplacePrefixMatch: utilpointer.String("foo"), + }, + }, + }, { + Type: gatewayv1a2.HTTPRouteFilterRequestRedirect, + RequestRedirect: &gatewayv1a2.HTTPRequestRedirectFilter{ + Path: &gatewayv1a2.HTTPPathModifier{ + Type: gatewayv1a2.PrefixMatchHTTPPathModifier, + ReplacePrefixMatch: utilpointer.String("foo"), + }, + }, + }}, + }}, }} for _, tc := range tests { @@ -654,7 +783,7 @@ func TestValidateHTTPRouteTypeMatchesField(t *testing.T) { routeFilter: gatewayv1a2.HTTPRouteFilter{ Type: gatewayv1a2.HTTPRouteFilterURLRewrite, URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{ - Hostname: new(gatewayv1a2.Hostname), + Hostname: new(gatewayv1a2.PreciseHostname), Path: &gatewayv1a2.HTTPPathModifier{}, }, }, diff --git a/apis/v1alpha2/zz_generated.deepcopy.go b/apis/v1alpha2/zz_generated.deepcopy.go index a09e3e31ed..c8d3d6bbb3 100644 --- a/apis/v1alpha2/zz_generated.deepcopy.go +++ b/apis/v1alpha2/zz_generated.deepcopy.go @@ -26,55 +26,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" ) -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AddressMatch) DeepCopyInto(out *AddressMatch) { - *out = *in - if in.Type != nil { - in, out := &in.Type, &out.Type - *out = new(AddressType) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressMatch. -func (in *AddressMatch) DeepCopy() *AddressMatch { - if in == nil { - return nil - } - out := new(AddressMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AddressRouteMatches) DeepCopyInto(out *AddressRouteMatches) { - *out = *in - if in.SourceAddresses != nil { - in, out := &in.SourceAddresses, &out.SourceAddresses - *out = make([]AddressMatch, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.DestinationAddresses != nil { - in, out := &in.DestinationAddresses, &out.DestinationAddresses - *out = make([]AddressMatch, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressRouteMatches. -func (in *AddressRouteMatches) DeepCopy() *AddressRouteMatches { - if in == nil { - return nil - } - out := new(AddressRouteMatches) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AllowedRoutes) DeepCopyInto(out *AllowedRoutes) { *out = *in @@ -440,13 +391,9 @@ func (in *GatewayTLSConfig) DeepCopyInto(out *GatewayTLSConfig) { } if in.CertificateRefs != nil { in, out := &in.CertificateRefs, &out.CertificateRefs - *out = make([]*SecretObjectReference, len(*in)) + *out = make([]SecretObjectReference, len(*in)) for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(SecretObjectReference) - (*in).DeepCopyInto(*out) - } + (*in)[i].DeepCopyInto(&(*out)[i]) } } if in.Options != nil { @@ -554,6 +501,16 @@ func (in *HTTPPathMatch) DeepCopy() *HTTPPathMatch { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPPathModifier) DeepCopyInto(out *HTTPPathModifier) { *out = *in + if in.ReplaceFullPath != nil { + in, out := &in.ReplaceFullPath, &out.ReplaceFullPath + *out = new(string) + **out = **in + } + if in.ReplacePrefixMatch != nil { + in, out := &in.ReplacePrefixMatch, &out.ReplacePrefixMatch + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPPathModifier. @@ -648,7 +605,7 @@ func (in *HTTPRequestRedirectFilter) DeepCopyInto(out *HTTPRequestRedirectFilter if in.Path != nil { in, out := &in.Path, &out.Path *out = new(HTTPPathModifier) - **out = **in + (*in).DeepCopyInto(*out) } if in.Port != nil { in, out := &in.Port, &out.Port @@ -895,13 +852,13 @@ func (in *HTTPURLRewriteFilter) DeepCopyInto(out *HTTPURLRewriteFilter) { *out = *in if in.Hostname != nil { in, out := &in.Hostname, &out.Hostname - *out = new(Hostname) + *out = new(PreciseHostname) **out = **in } if in.Path != nil { in, out := &in.Path, &out.Path *out = new(HTTPPathModifier) - **out = **in + (*in).DeepCopyInto(*out) } } @@ -1070,25 +1027,25 @@ func (in *PolicyTargetReference) DeepCopy() *PolicyTargetReference { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReferencePolicy) DeepCopyInto(out *ReferencePolicy) { +func (in *ReferenceGrant) DeepCopyInto(out *ReferenceGrant) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferencePolicy. -func (in *ReferencePolicy) DeepCopy() *ReferencePolicy { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrant. +func (in *ReferenceGrant) DeepCopy() *ReferenceGrant { if in == nil { return nil } - out := new(ReferencePolicy) + out := new(ReferenceGrant) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ReferencePolicy) DeepCopyObject() runtime.Object { +func (in *ReferenceGrant) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -1096,46 +1053,46 @@ func (in *ReferencePolicy) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReferencePolicyFrom) DeepCopyInto(out *ReferencePolicyFrom) { +func (in *ReferenceGrantFrom) DeepCopyInto(out *ReferenceGrantFrom) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferencePolicyFrom. -func (in *ReferencePolicyFrom) DeepCopy() *ReferencePolicyFrom { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrantFrom. +func (in *ReferenceGrantFrom) DeepCopy() *ReferenceGrantFrom { if in == nil { return nil } - out := new(ReferencePolicyFrom) + out := new(ReferenceGrantFrom) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReferencePolicyList) DeepCopyInto(out *ReferencePolicyList) { +func (in *ReferenceGrantList) DeepCopyInto(out *ReferenceGrantList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]ReferencePolicy, len(*in)) + *out = make([]ReferenceGrant, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferencePolicyList. -func (in *ReferencePolicyList) DeepCopy() *ReferencePolicyList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrantList. +func (in *ReferenceGrantList) DeepCopy() *ReferenceGrantList { if in == nil { return nil } - out := new(ReferencePolicyList) + out := new(ReferenceGrantList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ReferencePolicyList) DeepCopyObject() runtime.Object { +func (in *ReferenceGrantList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -1143,34 +1100,34 @@ func (in *ReferencePolicyList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReferencePolicySpec) DeepCopyInto(out *ReferencePolicySpec) { +func (in *ReferenceGrantSpec) DeepCopyInto(out *ReferenceGrantSpec) { *out = *in if in.From != nil { in, out := &in.From, &out.From - *out = make([]ReferencePolicyFrom, len(*in)) + *out = make([]ReferenceGrantFrom, len(*in)) copy(*out, *in) } if in.To != nil { in, out := &in.To, &out.To - *out = make([]ReferencePolicyTo, len(*in)) + *out = make([]ReferenceGrantTo, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferencePolicySpec. -func (in *ReferencePolicySpec) DeepCopy() *ReferencePolicySpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrantSpec. +func (in *ReferenceGrantSpec) DeepCopy() *ReferenceGrantSpec { if in == nil { return nil } - out := new(ReferencePolicySpec) + out := new(ReferenceGrantSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReferencePolicyTo) DeepCopyInto(out *ReferencePolicyTo) { +func (in *ReferenceGrantTo) DeepCopyInto(out *ReferenceGrantTo) { *out = *in if in.Name != nil { in, out := &in.Name, &out.Name @@ -1179,12 +1136,12 @@ func (in *ReferencePolicyTo) DeepCopyInto(out *ReferencePolicyTo) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferencePolicyTo. -func (in *ReferencePolicyTo) DeepCopy() *ReferencePolicyTo { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferenceGrantTo. +func (in *ReferenceGrantTo) DeepCopy() *ReferenceGrantTo { if in == nil { return nil } - out := new(ReferencePolicyTo) + out := new(ReferenceGrantTo) in.DeepCopyInto(out) return out } @@ -1371,13 +1328,6 @@ func (in *TCPRouteList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TCPRouteRule) DeepCopyInto(out *TCPRouteRule) { *out = *in - if in.Matches != nil { - in, out := &in.Matches, &out.Matches - *out = make([]AddressRouteMatches, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } if in.BackendRefs != nil { in, out := &in.BackendRefs, &out.BackendRefs *out = make([]BackendRef, len(*in)) @@ -1623,13 +1573,6 @@ func (in *UDPRouteList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UDPRouteRule) DeepCopyInto(out *UDPRouteRule) { *out = *in - if in.Matches != nil { - in, out := &in.Matches, &out.Matches - *out = make([]AddressRouteMatches, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } if in.BackendRefs != nil { in, out := &in.BackendRefs, &out.BackendRefs *out = make([]BackendRef, len(*in)) diff --git a/apis/v1alpha2/zz_generated.register.go b/apis/v1alpha2/zz_generated.register.go index 94dc2ff41b..7505084fa4 100644 --- a/apis/v1alpha2/zz_generated.register.go +++ b/apis/v1alpha2/zz_generated.register.go @@ -64,8 +64,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &GatewayList{}, &HTTPRoute{}, &HTTPRouteList{}, - &ReferencePolicy{}, - &ReferencePolicyList{}, + &ReferenceGrant{}, + &ReferenceGrantList{}, &TCPRoute{}, &TCPRouteList{}, &TLSRoute{}, diff --git a/apis/v1beta1/doc.go b/apis/v1beta1/doc.go new file mode 100644 index 0000000000..d29a3c14a2 --- /dev/null +++ b/apis/v1beta1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1beta1 contains API Schema definitions for the +// gateway.networking.k8s.io API group. +// +kubebuilder:object:generate=true +// +groupName=gateway.networking.k8s.io +package v1beta1 diff --git a/apis/v1beta1/gateway_types.go b/apis/v1beta1/gateway_types.go new file mode 100644 index 0000000000..2f7f73da5d --- /dev/null +++ b/apis/v1beta1/gateway_types.go @@ -0,0 +1,795 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=gateway-api,shortName=gtw +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:printcolumn:name="Class",type=string,JSONPath=`.spec.gatewayClassName` +// +kubebuilder:printcolumn:name="Address",type=string,JSONPath=`.status.addresses[*].value` +// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// Gateway represents an instance of a service-traffic handling infrastructure +// by binding Listeners to a set of IP addresses. +type Gateway struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of Gateway. + Spec GatewaySpec `json:"spec"` + + // Status defines the current state of Gateway. + // + // +kubebuilder:default={conditions: {{type: "Scheduled", status: "Unknown", reason:"NotReconciled", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + Status GatewayStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// GatewayList contains a list of Gateways. +type GatewayList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Gateway `json:"items"` +} + +// GatewaySpec defines the desired state of Gateway. +// +// Not all possible combinations of options specified in the Spec are +// valid. Some invalid configurations can be caught synchronously via a +// webhook, but there are many cases that will require asynchronous +// signaling via the GatewayStatus block. +type GatewaySpec struct { + // GatewayClassName used for this Gateway. This is the name of a + // GatewayClass resource. + GatewayClassName ObjectName `json:"gatewayClassName"` + + // Listeners associated with this Gateway. Listeners define + // logical endpoints that are bound on this Gateway's addresses. + // At least one Listener MUST be specified. + // + // Each listener in a Gateway must have a unique combination of Hostname, + // Port, and Protocol. + // + // An implementation MAY group Listeners by Port and then collapse each + // group of Listeners into a single Listener if the implementation + // determines that the Listeners in the group are "compatible". An + // implementation MAY also group together and collapse compatible + // Listeners belonging to different Gateways. + // + // For example, an implementation might consider Listeners to be + // compatible with each other if all of the following conditions are + // met: + // + // 1. Either each Listener within the group specifies the "HTTP" + // Protocol or each Listener within the group specifies either + // the "HTTPS" or "TLS" Protocol. + // + // 2. Each Listener within the group specifies a Hostname that is unique + // within the group. + // + // 3. As a special case, one Listener within a group may omit Hostname, + // in which case this Listener matches when no other Listener + // matches. + // + // If the implementation does collapse compatible Listeners, the + // hostname provided in the incoming client request MUST be + // matched to a Listener to find the correct set of Routes. + // The incoming hostname MUST be matched using the Hostname + // field for each Listener in order of most to least specific. + // That is, exact matches must be processed before wildcard + // matches. + // + // If this field specifies multiple Listeners that have the same + // Port value but are not compatible, the implementation must raise + // a "Conflicted" condition in the Listener status. + // + // Support: Core + // + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=64 + Listeners []Listener `json:"listeners"` + + // Addresses requested for this Gateway. This is optional and behavior can + // depend on the implementation. If a value is set in the spec and the + // requested address is invalid or unavailable, the implementation MUST + // indicate this in the associated entry in GatewayStatus.Addresses. + // + // The Addresses field represents a request for the address(es) on the + // "outside of the Gateway", that traffic bound for this Gateway will use. + // This could be the IP address or hostname of an external load balancer or + // other networking infrastructure, or some other address that traffic will + // be sent to. + // + // The .listener.hostname field is used to route traffic that has already + // arrived at the Gateway to the correct in-cluster destination. + // + // If no Addresses are specified, the implementation MAY schedule the + // Gateway in an implementation-specific manner, assigning an appropriate + // set of Addresses. + // + // The implementation MUST bind all Listeners to every GatewayAddress that + // it assigns to the Gateway and add a corresponding entry in + // GatewayStatus.Addresses. + // + // Support: Extended + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Addresses []GatewayAddress `json:"addresses,omitempty"` +} + +// Listener embodies the concept of a logical endpoint where a Gateway accepts +// network connections. +type Listener struct { + // Name is the name of the Listener. This name MUST be unique within a + // Gateway. + // + // Support: Core + Name SectionName `json:"name"` + + // Hostname specifies the virtual hostname to match for protocol types that + // define this concept. When unspecified, all hostnames are matched. This + // field is ignored for protocols that don't require hostname based + // matching. + // + // Implementations MUST apply Hostname matching appropriately for each of + // the following protocols: + // + // * TLS: The Listener Hostname MUST match the SNI. + // * HTTP: The Listener Hostname MUST match the Host header of the request. + // * HTTPS: The Listener Hostname SHOULD match at both the TLS and HTTP + // protocol layers as described above. If an implementation does not + // ensure that both the SNI and Host header match the Listener hostname, + // it MUST clearly document that. + // + // For HTTPRoute and TLSRoute resources, there is an interaction with the + // `spec.hostnames` array. When both listener and route specify hostnames, + // there MUST be an intersection between the values for a Route to be + // accepted. For more information, refer to the Route specific Hostnames + // documentation. + // + // Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + // as a suffix match. That means that a match for `*.example.com` would match + // both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + // + // Support: Core + // + // +optional + Hostname *Hostname `json:"hostname,omitempty"` + + // Port is the network port. Multiple listeners may use the + // same port, subject to the Listener compatibility rules. + // + // Support: Core + Port PortNumber `json:"port"` + + // Protocol specifies the network protocol this listener expects to receive. + // + // Support: Core + Protocol ProtocolType `json:"protocol"` + + // TLS is the TLS configuration for the Listener. This field is required if + // the Protocol field is "HTTPS" or "TLS". It is invalid to set this field + // if the Protocol field is "HTTP", "TCP", or "UDP". + // + // The association of SNIs to Certificate defined in GatewayTLSConfig is + // defined based on the Hostname field for this listener. + // + // The GatewayClass MUST use the longest matching SNI out of all + // available certificates for any TLS handshake. + // + // Support: Core + // + // +optional + TLS *GatewayTLSConfig `json:"tls,omitempty"` + + // AllowedRoutes defines the types of routes that MAY be attached to a + // Listener and the trusted namespaces where those Route resources MAY be + // present. + // + // Although a client request may match multiple route rules, only one rule + // may ultimately receive the request. Matching precedence MUST be + // determined in order of the following criteria: + // + // * The most specific match as defined by the Route type. + // * The oldest Route based on creation timestamp. For example, a Route with + // a creation timestamp of "2020-09-08 01:02:03" is given precedence over + // a Route with a creation timestamp of "2020-09-08 01:02:04". + // * If everything else is equivalent, the Route appearing first in + // alphabetical order (namespace/name) should be given precedence. For + // example, foo/bar is given precedence over foo/baz. + // + // All valid rules within a Route attached to this Listener should be + // implemented. Invalid Route rules can be ignored (sometimes that will mean + // the full Route). If a Route rule transitions from valid to invalid, + // support for that Route rule should be dropped to ensure consistency. For + // example, even if a filter specified by a Route rule is invalid, the rest + // of the rules within that Route should still be supported. + // + // Support: Core + // +kubebuilder:default={namespaces:{from: Same}} + // +optional + AllowedRoutes *AllowedRoutes `json:"allowedRoutes,omitempty"` +} + +// ProtocolType defines the application protocol accepted by a Listener. +// Implementations are not required to accept all the defined protocols. +// If an implementation does not support a specified protocol, it +// should raise a "Detached" condition for the affected Listener with +// a reason of "UnsupportedProtocol". +// +// Core ProtocolType values are listed in the table below. +// +// Implementations can define their own protocols if a core ProtocolType does not +// exist. Such definitions must use prefixed name, such as +// `mycompany.com/my-custom-protocol`. Un-prefixed names are reserved for core +// protocols. Any protocol defined by implementations will fall under custom +// conformance. +// +// Valid values include: +// +// * "HTTP" - Core support +// * "example.com/bar" - Implementation-specific support +// +// Invalid values include: +// +// * "example.com" - must include path if domain is used +// * "foo.example.com" - must include path if domain is used +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=255 +// +kubebuilder:validation:Pattern=`^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$` +type ProtocolType string + +const ( + // Accepts cleartext HTTP/1.1 sessions over TCP. Implementations MAY also + // support HTTP/2 over cleartext. If implementations support HTTP/2 over + // cleartext on "HTTP" listeners, that MUST be clearly documented by the + // implementation. + HTTPProtocolType ProtocolType = "HTTP" + + // Accepts HTTP/1.1 or HTTP/2 sessions over TLS. + HTTPSProtocolType ProtocolType = "HTTPS" + + // Accepts TLS sessions over TCP. + TLSProtocolType ProtocolType = "TLS" + + // Accepts TCP sessions. + TCPProtocolType ProtocolType = "TCP" + + // Accepts UDP packets. + UDPProtocolType ProtocolType = "UDP" +) + +// GatewayTLSConfig describes a TLS configuration. +type GatewayTLSConfig struct { + // Mode defines the TLS behavior for the TLS session initiated by the client. + // There are two possible modes: + // + // - Terminate: The TLS session between the downstream client + // and the Gateway is terminated at the Gateway. This mode requires + // certificateRefs to be set and contain at least one element. + // - Passthrough: The TLS session is NOT terminated by the Gateway. This + // implies that the Gateway can't decipher the TLS stream except for + // the ClientHello message of the TLS protocol. + // CertificateRefs field is ignored in this mode. + // + // Support: Core + // + // +optional + // +kubebuilder:default=Terminate + Mode *TLSModeType `json:"mode,omitempty"` + + // CertificateRefs contains a series of references to Kubernetes objects that + // contains TLS certificates and private keys. These certificates are used to + // establish a TLS handshake for requests that match the hostname of the + // associated listener. + // + // A single CertificateRef to a Kubernetes Secret has "Core" support. + // Implementations MAY choose to support attaching multiple certificates to + // a Listener, but this behavior is implementation-specific. + // + // References to a resource in different namespace are invalid UNLESS there + // is a ReferenceGrant in the target namespace that allows the certificate + // to be attached. If a ReferenceGrant does not allow this reference, the + // "ResolvedRefs" condition MUST be set to False for this listener with the + // "InvalidCertificateRef" reason. + // + // This field is required to have at least one element when the mode is set + // to "Terminate" (default) and is optional otherwise. + // + // CertificateRefs can reference to standard Kubernetes resources, i.e. + // Secret, or implementation-specific custom resources. + // + // Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls + // + // Support: Implementation-specific (More than one reference or other resource types) + // + // +optional + // +kubebuilder:validation:MaxItems=64 + CertificateRefs []SecretObjectReference `json:"certificateRefs,omitempty"` + + // Options are a list of key/value pairs to enable extended TLS + // configuration for each implementation. For example, configuring the + // minimum TLS version or supported cipher suites. + // + // A set of common keys MAY be defined by the API in the future. To avoid + // any ambiguity, implementation-specific definitions MUST use + // domain-prefixed names, such as `example.com/my-custom-option`. + // Un-prefixed names are reserved for key names defined by Gateway API. + // + // Support: Implementation-specific + // + // +optional + // +kubebuilder:validation:MaxProperties=16 + Options map[AnnotationKey]AnnotationValue `json:"options,omitempty"` +} + +// TLSModeType type defines how a Gateway handles TLS sessions. +// +// +kubebuilder:validation:Enum=Terminate;Passthrough +type TLSModeType string + +const ( + // In this mode, TLS session between the downstream client + // and the Gateway is terminated at the Gateway. + TLSModeTerminate TLSModeType = "Terminate" + + // In this mode, the TLS session is NOT terminated by the Gateway. This + // implies that the Gateway can't decipher the TLS stream except for + // the ClientHello message of the TLS protocol. + // + // Note that SSL passthrough is only supported by TLSRoute. + TLSModePassthrough TLSModeType = "Passthrough" +) + +// AllowedRoutes defines which Routes may be attached to this Listener. +type AllowedRoutes struct { + // Namespaces indicates namespaces from which Routes may be attached to this + // Listener. This is restricted to the namespace of this Gateway by default. + // + // Support: Core + // + // +optional + // +kubebuilder:default={from: Same} + Namespaces *RouteNamespaces `json:"namespaces,omitempty"` + + // Kinds specifies the groups and kinds of Routes that are allowed to bind + // to this Gateway Listener. When unspecified or empty, the kinds of Routes + // selected are determined using the Listener protocol. + // + // A RouteGroupKind MUST correspond to kinds of Routes that are compatible + // with the application protocol specified in the Listener's Protocol field. + // If an implementation does not support or recognize this resource type, it + // MUST set the "ResolvedRefs" condition to False for this Listener with the + // "InvalidRouteKinds" reason. + // + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=8 + Kinds []RouteGroupKind `json:"kinds,omitempty"` +} + +// FromNamespaces specifies namespace from which Routes may be attached to a +// Gateway. +// +// +kubebuilder:validation:Enum=All;Selector;Same +type FromNamespaces string + +const ( + // Routes in all namespaces may be attached to this Gateway. + NamespacesFromAll FromNamespaces = "All" + // Only Routes in namespaces selected by the selector may be attached to + // this Gateway. + NamespacesFromSelector FromNamespaces = "Selector" + // Only Routes in the same namespace as the Gateway may be attached to this + // Gateway. + NamespacesFromSame FromNamespaces = "Same" +) + +// RouteNamespaces indicate which namespaces Routes should be selected from. +type RouteNamespaces struct { + // From indicates where Routes will be selected for this Gateway. Possible + // values are: + // * All: Routes in all namespaces may be used by this Gateway. + // * Selector: Routes in namespaces selected by the selector may be used by + // this Gateway. + // * Same: Only Routes in the same namespace may be used by this Gateway. + // + // Support: Core + // + // +optional + // +kubebuilder:default=Same + From *FromNamespaces `json:"from,omitempty"` + + // Selector must be specified when From is set to "Selector". In that case, + // only Routes in Namespaces matching this Selector will be selected by this + // Gateway. This field is ignored for other values of "From". + // + // Support: Core + // + // +optional + Selector *metav1.LabelSelector `json:"selector,omitempty"` +} + +// RouteGroupKind indicates the group and kind of a Route resource. +type RouteGroupKind struct { + // Group is the group of the Route. + // + // +optional + // +kubebuilder:default=gateway.networking.k8s.io + Group *Group `json:"group,omitempty"` + + // Kind is the kind of the Route. + Kind Kind `json:"kind"` +} + +// GatewayAddress describes an address that can be bound to a Gateway. +type GatewayAddress struct { + // Type of the address. + // + // +optional + // +kubebuilder:validation:Enum=IPAddress;Hostname;NamedAddress + // +kubebuilder:default=IPAddress + Type *AddressType `json:"type,omitempty"` + + // Value of the address. The validity of the values will depend + // on the type and support by the controller. + // + // Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Value string `json:"value"` +} + +// GatewayStatus defines the observed state of Gateway. +type GatewayStatus struct { + // Addresses lists the IP addresses that have actually been + // bound to the Gateway. These addresses may differ from the + // addresses in the Spec, e.g. if the Gateway automatically + // assigns an address from a reserved pool. + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Addresses []GatewayAddress `json:"addresses,omitempty"` + + // Conditions describe the current conditions of the Gateway. + // + // Implementations should prefer to express Gateway conditions + // using the `GatewayConditionType` and `GatewayConditionReason` + // constants so that operators and tools can converge on a common + // vocabulary to describe Gateway state. + // + // Known condition types are: + // + // * "Scheduled" + // * "Ready" + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:default={{type: "Scheduled", status: "Unknown", reason:"NotReconciled", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}} + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // Listeners provide status for each unique listener port defined in the Spec. + // + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=64 + Listeners []ListenerStatus `json:"listeners,omitempty"` +} + +// GatewayConditionType is a type of condition associated with a +// Gateway. This type should be used with the GatewayStatus.Conditions +// field. +type GatewayConditionType string + +// GatewayConditionReason defines the set of reasons that explain why a +// particular Gateway condition type has been raised. +type GatewayConditionReason string + +const ( + // This condition is true when the controller managing the + // Gateway has scheduled the Gateway to the underlying network + // infrastructure. + // + // Possible reasons for this condition to be true are: + // + // * "Scheduled" + // + // Possible reasons for this condition to be False are: + // + // * "NotReconciled" + // * "NoResources" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + GatewayConditionScheduled GatewayConditionType = "Scheduled" + + // This reason is used with the "Scheduled" condition when the condition is + // true. + GatewayReasonScheduled GatewayConditionReason = "Scheduled" + + // This reason is used with the "Scheduled" condition when no controller has + // reconciled the Gateway. + GatewayReasonNotReconciled GatewayConditionReason = "NotReconciled" + + // This reason is used with the "Scheduled" condition when the + // Gateway is not scheduled because insufficient infrastructure + // resources are available. + GatewayReasonNoResources GatewayConditionReason = "NoResources" +) + +const ( + // This condition is true when the Gateway is expected to be able + // to serve traffic. Note that this does not indicate that the + // Gateway configuration is current or even complete (e.g. the + // controller may still not have reconciled the latest version, + // or some parts of the configuration could be missing). + // + // If both the "ListenersNotValid" and "ListenersNotReady" + // reasons are true, the Gateway controller should prefer the + // "ListenersNotValid" reason. + // + // Possible reasons for this condition to be true are: + // + // * "Ready" + // + // Possible reasons for this condition to be False are: + // + // * "ListenersNotValid" + // * "ListenersNotReady" + // * "AddressNotAssigned" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + GatewayConditionReady GatewayConditionType = "Ready" + + // This reason is used with the "Ready" condition when the condition is + // true. + GatewayReasonReady GatewayConditionReason = "Ready" + + // This reason is used with the "Ready" condition when one or + // more Listeners have an invalid or unsupported configuration + // and cannot be configured on the Gateway. + GatewayReasonListenersNotValid GatewayConditionReason = "ListenersNotValid" + + // This reason is used with the "Ready" condition when one or + // more Listeners are not ready to serve traffic. + GatewayReasonListenersNotReady GatewayConditionReason = "ListenersNotReady" + + // This reason is used with the "Ready" condition when none of the requested + // addresses have been assigned to the Gateway. This reason can be used to + // express a range of circumstances, including (but not limited to) IPAM + // address exhaustion, invalid or unsupported address requests, or a named + // address not being found. + GatewayReasonAddressNotAssigned GatewayConditionReason = "AddressNotAssigned" +) + +// ListenerStatus is the status associated with a Listener. +type ListenerStatus struct { + // Name is the name of the Listener that this status corresponds to. + Name SectionName `json:"name"` + + // SupportedKinds is the list indicating the Kinds supported by this + // listener. This MUST represent the kinds an implementation supports for + // that Listener configuration. + // + // If kinds are specified in Spec that are not supported, they MUST NOT + // appear in this list and an implementation MUST set the "ResolvedRefs" + // condition to "False" with the "InvalidRouteKinds" reason. If both valid + // and invalid Route kinds are specified, the implementation MUST + // reference the valid Route kinds that have been specified. + // + // +kubebuilder:validation:MaxItems=8 + SupportedKinds []RouteGroupKind `json:"supportedKinds"` + + // AttachedRoutes represents the total number of Routes that have been + // successfully attached to this Listener. + AttachedRoutes int32 `json:"attachedRoutes"` + + // Conditions describe the current condition of this listener. + // + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions"` +} + +// ListenerConditionType is a type of condition associated with the +// listener. This type should be used with the ListenerStatus.Conditions +// field. +type ListenerConditionType string + +// ListenerConditionReason defines the set of reasons that explain +// why a particular Listener condition type has been raised. +type ListenerConditionReason string + +const ( + // This condition indicates that the controller was unable to resolve + // conflicting specification requirements for this Listener. If a + // Listener is conflicted, its network port should not be configured + // on any network elements. + // + // Possible reasons for this condition to be true are: + // + // * "HostnameConflict" + // * "ProtocolConflict" + // + // Possible reasons for this condition to be False are: + // + // * "NoConflicts" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + ListenerConditionConflicted ListenerConditionType = "Conflicted" + + // This reason is used with the "Conflicted" condition when + // the Listener conflicts with hostnames in other Listeners. For + // example, this reason would be used when multiple Listeners on + // the same port use `example.com` in the hostname field. + ListenerReasonHostnameConflict ListenerConditionReason = "HostnameConflict" + + // This reason is used with the "Conflicted" condition when + // multiple Listeners are specified with the same Listener port + // number, but have conflicting protocol specifications. + ListenerReasonProtocolConflict ListenerConditionReason = "ProtocolConflict" + + // This reason is used with the "Conflicted" condition when the condition + // is False. + ListenerReasonNoConflicts ListenerConditionReason = "NoConflicts" +) + +const ( + // This condition indicates that, even though the listener is + // syntactically and semantically valid, the controller is not able + // to configure it on the underlying Gateway infrastructure. + // + // A Listener is specified as a logical requirement, but needs to be + // configured on a network endpoint (i.e. address and port) by a + // controller. The controller may be unable to attach the Listener + // if it specifies an unsupported requirement, or prerequisite + // resources are not available. + // + // Possible reasons for this condition to be true are: + // + // * "PortUnavailable" + // * "UnsupportedProtocol" + // * "UnsupportedAddress" + // + // Possible reasons for this condition to be False are: + // + // * "Attached" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + ListenerConditionDetached ListenerConditionType = "Detached" + + // This reason is used with the "Detached" condition when the Listener + // requests a port that cannot be used on the Gateway. This reason could be + // used in a number of instances, including: + // + // * The port is already in use. + // * The port is not supported by the implementation. + ListenerReasonPortUnavailable ListenerConditionReason = "PortUnavailable" + + // This reason is used with the "Detached" condition when the + // Listener could not be attached to be Gateway because its + // protocol type is not supported. + ListenerReasonUnsupportedProtocol ListenerConditionReason = "UnsupportedProtocol" + + // This reason is used with the "Detached" condition when the Listener could + // not be attached to the Gateway because the requested address is not + // supported. This reason could be used in a number of instances, including: + // + // * The address is already in use. + // * The type of address is not supported by the implementation. + ListenerReasonUnsupportedAddress ListenerConditionReason = "UnsupportedAddress" + + // This reason is used with the "Detached" condition when the condition is + // False. + ListenerReasonAttached ListenerConditionReason = "Attached" +) + +const ( + // This condition indicates whether the controller was able to + // resolve all the object references for the Listener. + // + // Possible reasons for this condition to be true are: + // + // * "ResolvedRefs" + // + // Possible reasons for this condition to be False are: + // + // * "InvalidCertificateRef" + // * "InvalidRouteKinds" + // * "RefNotPermitted" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + ListenerConditionResolvedRefs ListenerConditionType = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the condition + // is true. + ListenerReasonResolvedRefs ListenerConditionReason = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the + // Listener has a TLS configuration with at least one TLS CertificateRef + // that is invalid or cannot be resolved. + ListenerReasonInvalidCertificateRef ListenerConditionReason = "InvalidCertificateRef" + + // This reason is used with the "ResolvedRefs" condition when an invalid or + // unsupported Route kind is specified by the Listener. + ListenerReasonInvalidRouteKinds ListenerConditionReason = "InvalidRouteKinds" + + // This reason is used with the "ResolvedRefs" condition when + // one of the Listener's Routes has a BackendRef to an object in + // another namespace, where the object in the other namespace does + // not have a ReferenceGrant explicitly allowing the reference. + ListenerReasonRefNotPermitted ListenerConditionReason = "RefNotPermitted" +) + +const ( + // This condition indicates whether the Listener has been + // configured on the Gateway. + // + // Possible reasons for this condition to be true are: + // + // * "Ready" + // + // Possible reasons for this condition to be False are: + // + // * "Invalid" + // * "Pending" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + ListenerConditionReady ListenerConditionType = "Ready" + + // This reason is used with the "Ready" condition when the condition is + // true. + ListenerReasonReady ListenerConditionReason = "Ready" + + // This reason is used with the "Ready" condition when the + // Listener is syntactically or semantically invalid. + ListenerReasonInvalid ListenerConditionReason = "Invalid" + + // This reason is used with the "Ready" condition when the + // Listener is not yet not online and ready to accept client + // traffic. + ListenerReasonPending ListenerConditionReason = "Pending" +) diff --git a/apis/v1beta1/gatewayclass_types.go b/apis/v1beta1/gatewayclass_types.go new file mode 100644 index 0000000000..ee1a5c5af0 --- /dev/null +++ b/apis/v1beta1/gatewayclass_types.go @@ -0,0 +1,201 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=gateway-api,scope=Cluster,shortName=gc +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:printcolumn:name="Controller",type=string,JSONPath=`.spec.controllerName` +// +kubebuilder:printcolumn:name="Accepted",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].status` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:printcolumn:name="Description",type=string,JSONPath=`.spec.description`,priority=1 + +// GatewayClass describes a class of Gateways available to the user for creating +// Gateway resources. +// +// It is recommended that this resource be used as a template for Gateways. This +// means that a Gateway is based on the state of the GatewayClass at the time it +// was created and changes to the GatewayClass or associated parameters are not +// propagated down to existing Gateways. This recommendation is intended to +// limit the blast radius of changes to GatewayClass or associated parameters. +// If implementations choose to propagate GatewayClass changes to existing +// Gateways, that MUST be clearly documented by the implementation. +// +// Whenever one or more Gateways are using a GatewayClass, implementations MUST +// add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the +// associated GatewayClass. This ensures that a GatewayClass associated with a +// Gateway is not deleted while in use. +// +// GatewayClass is a Cluster level resource. +type GatewayClass struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of GatewayClass. + Spec GatewayClassSpec `json:"spec"` + + // Status defines the current state of GatewayClass. + // + // +kubebuilder:default={conditions: {{type: "Accepted", status: "Unknown", message: "Waiting for controller", reason: "Waiting", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + Status GatewayClassStatus `json:"status,omitempty"` +} + +const ( + // GatewayClassFinalizerGatewaysExist should be added as a finalizer to the + // GatewayClass whenever there are provisioned Gateways using a + // GatewayClass. + GatewayClassFinalizerGatewaysExist = "gateway-exists-finalizer.gateway.networking.k8s.io" +) + +// GatewayClassSpec reflects the configuration of a class of Gateways. +type GatewayClassSpec struct { + // ControllerName is the name of the controller that is managing Gateways of + // this class. The value of this field MUST be a domain prefixed path. + // + // Example: "example.net/gateway-controller". + // + // This field is not mutable and cannot be empty. + // + // Support: Core + ControllerName GatewayController `json:"controllerName"` + + // ParametersRef is a reference to a resource that contains the configuration + // parameters corresponding to the GatewayClass. This is optional if the + // controller does not require any additional configuration. + // + // ParametersRef can reference a standard Kubernetes resource, i.e. ConfigMap, + // or an implementation-specific custom resource. The resource can be + // cluster-scoped or namespace-scoped. + // + // If the referent cannot be found, the GatewayClass's "InvalidParameters" + // status condition will be true. + // + // Support: Custom + // + // +optional + ParametersRef *ParametersReference `json:"parametersRef,omitempty"` + + // Description helps describe a GatewayClass with more details. + // + // +kubebuilder:validation:MaxLength=64 + // +optional + Description *string `json:"description,omitempty"` +} + +// ParametersReference identifies an API object containing controller-specific +// configuration resource within the cluster. +type ParametersReference struct { + // Group is the group of the referent. + Group Group `json:"group"` + + // Kind is kind of the referent. + Kind Kind `json:"kind"` + + // Name is the name of the referent. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Name string `json:"name"` + + // Namespace is the namespace of the referent. + // This field is required when referring to a Namespace-scoped resource and + // MUST be unset when referring to a Cluster-scoped resource. + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` +} + +// GatewayClassConditionType is the type for status conditions on +// Gateway resources. This type should be used with the +// GatewayClassStatus.Conditions field. +type GatewayClassConditionType string + +// GatewayClassConditionReason defines the set of reasons that explain why a +// particular GatewayClass condition type has been raised. +type GatewayClassConditionReason string + +const ( + // This condition indicates whether the GatewayClass has been accepted by + // the controller requested in the `spec.controller` field. + // + // This condition defaults to Unknown, and MUST be set by a controller when + // it sees a GatewayClass using its controller string. The status of this + // condition MUST be set to True if the controller will support provisioning + // Gateways using this class. Otherwise, this status MUST be set to False. + // If the status is set to False, the controller SHOULD set a Message and + // Reason as an explanation. + // + // Possible reasons for this condition to be true are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "InvalidParameters" + // * "Waiting" + // + // Controllers should prefer to use the values of GatewayClassConditionReason + // for the corresponding Reason, where appropriate. + GatewayClassConditionStatusAccepted GatewayClassConditionType = "Accepted" + + // This reason is used with the "Accepted" condition when the condition is + // true. + GatewayClassReasonAccepted GatewayClassConditionReason = "Accepted" + + // This reason is used with the "Accepted" condition when the + // GatewayClass was not accepted because the parametersRef field + // was invalid, with more detail in the message. + GatewayClassReasonInvalidParameters GatewayClassConditionReason = "InvalidParameters" + + // This reason is used with the "Accepted" condition when the + // requested controller has not yet made a decision about whether + // to admit the GatewayClass. It is the default Reason on a new + // GatewayClass. + GatewayClassReasonWaiting GatewayClassConditionReason = "Waiting" +) + +// GatewayClassStatus is the current status for the GatewayClass. +type GatewayClassStatus struct { + // Conditions is the current status from the controller for + // this GatewayClass. + // + // Controllers should prefer to publish conditions using values + // of GatewayClassConditionType for the type of each Condition. + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:default={{type: "Accepted", status: "Unknown", message: "Waiting for controller", reason: "Waiting", lastTransitionTime: "1970-01-01T00:00:00Z"}} + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true + +// GatewayClassList contains a list of GatewayClass +type GatewayClassList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []GatewayClass `json:"items"` +} diff --git a/apis/v1beta1/httproute_types.go b/apis/v1beta1/httproute_types.go new file mode 100644 index 0000000000..9e978e8303 --- /dev/null +++ b/apis/v1beta1/httproute_types.go @@ -0,0 +1,886 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +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` + +// HTTPRoute provides a way to route HTTP requests. This includes the capability +// to match requests by hostname, path, header, or query param. Filters can be +// used to specify additional processing steps. Backends specify where matching +// requests should be routed. +type HTTPRoute struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of HTTPRoute. + Spec HTTPRouteSpec `json:"spec"` + + // Status defines the current state of HTTPRoute. + Status HTTPRouteStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// HTTPRouteList contains a list of HTTPRoute. +type HTTPRouteList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []HTTPRoute `json:"items"` +} + +// HTTPRouteSpec defines the desired state of HTTPRoute +type HTTPRouteSpec struct { + CommonRouteSpec `json:",inline"` + + // Hostnames defines a set of hostname that should match against the HTTP + // Host header to select a HTTPRoute to process the request. This matches + // the RFC 1123 definition of a hostname with 2 notable exceptions: + // + // 1. IPs are not allowed. + // 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + // label must appear by itself as the first label. + // + // If a hostname is specified by both the Listener and HTTPRoute, there + // must be at least one intersecting hostname for the HTTPRoute to be + // attached to the Listener. For example: + // + // * A Listener with `test.example.com` as the hostname matches HTTPRoutes + // that have either not specified any hostnames, or have specified at + // least one of `test.example.com` or `*.example.com`. + // * A Listener with `*.example.com` as the hostname matches HTTPRoutes + // that have either not specified any hostnames or have specified at least + // one hostname that matches the Listener hostname. For example, + // `*.example.com`, `test.example.com`, and `foo.test.example.com` would + // all match. On the other hand, `example.com` and `test.example.net` would + // not match. + // + // Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + // as a suffix match. That means that a match for `*.example.com` would match + // both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + // + // If both the Listener and HTTPRoute have specified hostnames, any + // HTTPRoute hostnames that do not match the Listener hostname MUST be + // ignored. For example, if a Listener specified `*.example.com`, and the + // HTTPRoute specified `test.example.com` and `test.example.net`, + // `test.example.net` must not be considered for a match. + // + // If both the Listener and HTTPRoute have specified hostnames, and none + // match with the criteria above, then the HTTPRoute is not accepted. The + // implementation must raise an 'Accepted' Condition with a status of + // `False` in the corresponding RouteParentStatus. + // + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Hostnames []Hostname `json:"hostnames,omitempty"` + + // Rules are a list of HTTP matchers, filters and actions. + // + // +optional + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:default={{matches: {{path: {type: "PathPrefix", value: "/"}}}}} + Rules []HTTPRouteRule `json:"rules,omitempty"` +} + +// HTTPRouteRule defines semantics for matching an HTTP request based on +// conditions (matches), processing it (filters), and forwarding the request to +// an API object (backendRefs). +type HTTPRouteRule struct { + // Matches define conditions used for matching the rule against incoming + // HTTP requests. Each match is independent, i.e. this rule will be matched + // if **any** one of the matches is satisfied. + // + // For example, take the following matches configuration: + // + // ``` + // matches: + // - path: + // value: "/foo" + // headers: + // - name: "version" + // value: "v2" + // - path: + // value: "/v2/foo" + // ``` + // + // For a request to match against this rule, a request must satisfy + // EITHER of the two conditions: + // + // - path prefixed with `/foo` AND contains the header `version: v2` + // - path prefix of `/v2/foo` + // + // See the documentation for HTTPRouteMatch on how to specify multiple + // match conditions that should be ANDed together. + // + // If no matches are specified, the default is a prefix + // path match on "/", which has the effect of matching every + // HTTP request. + // + // Proxy or Load Balancer routing configuration generated from HTTPRoutes + // MUST prioritize rules based on the following criteria, continuing on + // ties. Precedence must be given to the the Rule with the largest number + // of: + // + // * Characters in a matching non-wildcard hostname. + // * Characters in a matching hostname. + // * Characters in a matching path. + // * Header matches. + // * Query param matches. + // + // If ties still exist across multiple Routes, matching precedence MUST be + // determined in order of the following criteria, continuing on ties: + // + // * The oldest Route based on creation timestamp. + // * 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. + // + // When no rules matching a request have been successfully attached to the + // parent a request is coming from, a HTTP 404 status code MUST be returned. + // + // +optional + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:default={{path:{ type: "PathPrefix", value: "/"}}} + Matches []HTTPRouteMatch `json:"matches,omitempty"` + + // Filters define the filters that are applied to requests that match + // this rule. + // + // The effects of ordering of multiple behaviors are currently unspecified. + // This can change in the future based on feedback during the alpha stage. + // + // Conformance-levels at this level are defined based on the type of filter: + // + // - ALL core filters MUST be supported by all implementations. + // - Implementers are encouraged to support extended filters. + // - Implementation-specific custom filters have no API guarantees across + // implementations. + // + // Specifying a core filter multiple times has unspecified or custom + // conformance. + // + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Filters []HTTPRouteFilter `json:"filters,omitempty"` + + // BackendRefs defines the backend(s) where matching requests should be + // sent. + // + // A 404 status code 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, 404 status codes MUST be returned for + // requests that would have otherwise been routed to an invalid backend. If + // multiple backends are specified, and some are invalid, the proportion of + // requests that would otherwise have been routed to an invalid backend + // MUST receive a 404 status code. + // + // When a BackendRef refers to a Service that has no ready endpoints, it is + // recommended to return a 503 status code. + // + // Support: Core for Kubernetes Service + // Support: Custom for any other resource + // + // Support for weight: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + BackendRefs []HTTPBackendRef `json:"backendRefs,omitempty"` +} + +// PathMatchType specifies the semantics of how HTTP paths should be compared. +// Valid PathMatchType values are: +// +// * "Exact" +// * "PathPrefix" +// * "RegularExpression" +// +// PathPrefix and Exact paths must be syntactically valid: +// +// - Must begin with the `/` character +// - Must not contain consecutive `/` characters (e.g. `/foo///`, `//`). +// +// +kubebuilder:validation:Enum=Exact;PathPrefix;RegularExpression +type PathMatchType string + +const ( + // Matches the URL path exactly and with case sensitivity. + PathMatchExact PathMatchType = "Exact" + + // Matches based on a URL path prefix split by `/`. Matching is + // case sensitive and done on a path element by element basis. A + // path element refers to the list of labels in the path split by + // the `/` separator. When specified, a trailing `/` is ignored. + // + // For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match + // the prefix `/abc`, but the path `/abcd` would not. + // + // "PathPrefix" is semantically equivalent to the "Prefix" path type in the + // Kubernetes Ingress API. + PathMatchPathPrefix PathMatchType = "PathPrefix" + + // Matches if the URL path matches the given regular expression with + // case sensitivity. + // + // Since `"RegularExpression"` has custom conformance, implementations + // can support POSIX, PCRE, RE2 or any other regular expression dialect. + // Please read the implementation's documentation to determine the supported + // dialect. + PathMatchRegularExpression PathMatchType = "RegularExpression" +) + +// HTTPPathMatch describes how to select a HTTP route by matching the HTTP request path. +type HTTPPathMatch struct { + // Type specifies how to match against the path Value. + // + // Support: Core (Exact, PathPrefix) + // + // Support: Custom (RegularExpression) + // + // +optional + // +kubebuilder:default=PathPrefix + Type *PathMatchType `json:"type,omitempty"` + + // Value of the HTTP path to match against. + // + // +optional + // +kubebuilder:default="/" + // +kubebuilder:validation:MaxLength=1024 + Value *string `json:"value,omitempty"` +} + +// HeaderMatchType specifies the semantics of how HTTP header values should be +// compared. Valid HeaderMatchType values are: +// +// * "Exact" +// * "RegularExpression" +// +// +kubebuilder:validation:Enum=Exact;RegularExpression +type HeaderMatchType string + +// HeaderMatchType constants. +const ( + HeaderMatchExact HeaderMatchType = "Exact" + HeaderMatchRegularExpression HeaderMatchType = "RegularExpression" +) + +// HTTPHeaderName is the name of an HTTP header. +// +// Valid values include: +// +// * "Authorization" +// * "Set-Cookie" +// +// Invalid values include: +// +// * ":method" - ":" is an invalid character. This means that HTTP/2 pseudo +// headers are not currently supported by this type. +// * "/invalid" - "/" is an invalid character +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=256 +// +kubebuilder:validation:Pattern=`^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$` +type HTTPHeaderName string + +// HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request +// headers. +type HTTPHeaderMatch struct { + // Type specifies how to match against the value of the header. + // + // Support: Core (Exact) + // + // Support: Custom (RegularExpression) + // + // Since RegularExpression HeaderMatchType has custom conformance, + // implementations can support POSIX, PCRE or any other dialects of regular + // expressions. Please read the implementation's documentation to determine + // the supported dialect. + // + // +optional + // +kubebuilder:default=Exact + Type *HeaderMatchType `json:"type,omitempty"` + + // Name is the name of the HTTP Header to be matched. Name matching MUST be + // case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + // + // If multiple entries specify equivalent header names, only the first + // entry with an equivalent name MUST be considered for a match. Subsequent + // entries with an equivalent header name MUST be ignored. Due to the + // case-insensitivity of header names, "foo" and "Foo" are considered + // equivalent. + // + // When a header is repeated in an HTTP request, it is + // implementation-specific behavior as to how this is represented. + // Generally, proxies should follow the guidance from the RFC: + // https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + // processing a repeated header, with special handling for "Set-Cookie". + Name HTTPHeaderName `json:"name"` + + // Value is the value of HTTP Header to be matched. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=4096 + Value string `json:"value"` +} + +// QueryParamMatchType specifies the semantics of how HTTP query parameter +// values should be compared. Valid QueryParamMatchType values are: +// +// * "Exact" +// * "RegularExpression" +// +// +kubebuilder:validation:Enum=Exact;RegularExpression +type QueryParamMatchType string + +// QueryParamMatchType constants. +const ( + QueryParamMatchExact QueryParamMatchType = "Exact" + QueryParamMatchRegularExpression QueryParamMatchType = "RegularExpression" +) + +// HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP +// query parameters. +type HTTPQueryParamMatch struct { + // Type specifies how to match against the value of the query parameter. + // + // Support: Extended (Exact) + // + // Support: Custom (RegularExpression) + // + // Since RegularExpression QueryParamMatchType has custom conformance, + // implementations can support POSIX, PCRE or any other dialects of regular + // expressions. Please read the implementation's documentation to determine + // the supported dialect. + // + // +optional + // +kubebuilder:default=Exact + Type *QueryParamMatchType `json:"type,omitempty"` + + // Name is the name of the HTTP query param to be matched. This must be an + // exact string match. (See + // https://tools.ietf.org/html/rfc7230#section-2.7.3). + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=256 + Name string `json:"name"` + + // Value is the value of HTTP query param to be matched. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1024 + Value string `json:"value"` +} + +// HTTPMethod describes how to select a HTTP route by matching the HTTP +// method as defined by +// [RFC 7231](https://datatracker.ietf.org/doc/html/rfc7231#section-4) and +// [RFC 5789](https://datatracker.ietf.org/doc/html/rfc5789#section-2). +// The value is expected in upper case. +// +kubebuilder:validation:Enum=GET;HEAD;POST;PUT;DELETE;CONNECT;OPTIONS;TRACE;PATCH +type HTTPMethod string + +const ( + HTTPMethodGet HTTPMethod = "GET" + HTTPMethodHead HTTPMethod = "HEAD" + HTTPMethodPost HTTPMethod = "POST" + HTTPMethodPut HTTPMethod = "PUT" + HTTPMethodDelete HTTPMethod = "DELETE" + HTTPMethodConnect HTTPMethod = "CONNECT" + HTTPMethodOptions HTTPMethod = "OPTIONS" + HTTPMethodTrace HTTPMethod = "TRACE" + HTTPMethodPatch HTTPMethod = "PATCH" +) + +// HTTPRouteMatch defines the predicate used to match requests to a given +// action. Multiple match types are ANDed together, i.e. the match will +// evaluate to true only if all conditions are satisfied. +// +// For example, the match below will match a HTTP request only if its path +// starts with `/foo` AND it contains the `version: v1` header: +// +// ``` +// match: +// path: +// value: "/foo" +// headers: +// - name: "version" +// value "v1" +// ``` +type HTTPRouteMatch struct { + // Path specifies a HTTP request path matcher. If this field is not + // specified, a default prefix match on the "/" path is provided. + // + // +optional + // +kubebuilder:default={type: "PathPrefix", value: "/"} + Path *HTTPPathMatch `json:"path,omitempty"` + + // Headers specifies HTTP request header matchers. Multiple match values are + // ANDed together, meaning, a request must match all the specified headers + // to select the route. + // + // +listType=map + // +listMapKey=name + // +optional + // +kubebuilder:validation:MaxItems=16 + Headers []HTTPHeaderMatch `json:"headers,omitempty"` + + // QueryParams specifies HTTP query parameter matchers. Multiple match + // values are ANDed together, meaning, a request must match all the + // specified query parameters to select the route. + // + // +listType=map + // +listMapKey=name + // +optional + // +kubebuilder:validation:MaxItems=16 + QueryParams []HTTPQueryParamMatch `json:"queryParams,omitempty"` + + // Method specifies HTTP method matcher. + // When specified, this route will be matched only if the request has the + // specified method. + // + // Support: Extended + // + // +optional + Method *HTTPMethod `json:"method,omitempty"` +} + +// HTTPRouteFilter defines processing steps that must be completed during the +// request or response lifecycle. HTTPRouteFilters are meant as an extension +// point to express processing that may be done in Gateway implementations. Some +// examples include request or response modification, implementing +// authentication strategies, rate-limiting, and traffic shaping. API +// guarantee/conformance is defined based on the type of the filter. +type HTTPRouteFilter struct { + // Type identifies the type of filter to apply. As with other API fields, + // types are classified into three conformance levels: + // + // - Core: Filter types and their corresponding configuration defined by + // "Support: Core" in this package, e.g. "RequestHeaderModifier". All + // implementations must support core filters. + // + // - Extended: Filter types and their corresponding configuration defined by + // "Support: Extended" in this package, e.g. "RequestMirror". Implementers + // are encouraged to support extended filters. + // + // - 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;RequestRedirect;ExtensionRef + // + Type HTTPRouteFilterType `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"` + + // RequestRedirect defines a schema for a filter that responds to the + // request with an HTTP redirection. + // + // Support: Core + // + // +optional + RequestRedirect *HTTPRequestRedirectFilter `json:"requestRedirect,omitempty"` + + // URLRewrite defines a schema for a filter that modifies a request during forwarding. + // Support: Extended + // + // + // +optional + URLRewrite *HTTPURLRewriteFilter `json:"urlRewrite,omitempty"` + + // ExtensionRef is an optional, implementation-specific extension to the + // "filter" behavior. For example, resource "myroutefilter" in group + // "networking.example.net"). ExtensionRef MUST NOT be used for core and + // extended filters. + // + // Support: Implementation-specific + // + // +optional + ExtensionRef *LocalObjectReference `json:"extensionRef,omitempty"` +} + +// HTTPRouteFilterType identifies a type of HTTPRoute filter. +type HTTPRouteFilterType string + +const ( + // HTTPRouteFilterRequestHeaderModifier can be used to add or remove an HTTP + // header from an HTTP request before it is sent to the upstream target. + // + // Support in HTTPRouteRule: Core + // + // Support in HTTPBackendRef: Extended + HTTPRouteFilterRequestHeaderModifier HTTPRouteFilterType = "RequestHeaderModifier" + + // HTTPRouteFilterRequestRedirect can be used to redirect a request to + // another location. This filter can also be used for HTTP to HTTPS + // redirects. This may not be used on the same Route rule or BackendRef as a + // URLRewrite filter. + // + // Support in HTTPRouteRule: Core + // + // Support in HTTPBackendRef: Extended + HTTPRouteFilterRequestRedirect HTTPRouteFilterType = "RequestRedirect" + + // HTTPRouteFilterURLRewrite can be used to modify a request during + // forwarding. At most one of these filters may be used on a Route rule. + // This may not be used on the same Route rule or BackendRef as a + // RequestRedirect filter. + // + // Support in HTTPRouteRule: Extended + // + // Support in HTTPBackendRef: Extended + // + // + HTTPRouteFilterURLRewrite HTTPRouteFilterType = "URLRewrite" + + // HTTPRouteFilterRequestMirror can be used to mirror HTTP requests to a + // different backend. The responses from this backend MUST be ignored by + // the Gateway. + // + // Support in HTTPRouteRule: Extended + // + // Support in HTTPBackendRef: Extended + HTTPRouteFilterRequestMirror HTTPRouteFilterType = "RequestMirror" + + // HTTPRouteFilterExtensionRef should be used for configuring custom + // HTTP filters. + // + // Support in HTTPRouteRule: Custom + // + // Support in HTTPBackendRef: Custom + HTTPRouteFilterExtensionRef HTTPRouteFilterType = "ExtensionRef" +) + +// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. +type HTTPHeader struct { + // Name is the name of the HTTP Header to be matched. Name matching MUST be + // case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + // + // If multiple entries specify equivalent header names, the first entry with + // an equivalent name MUST be considered for a match. Subsequent entries + // with an equivalent header name MUST be ignored. Due to the + // case-insensitivity of header names, "foo" and "Foo" are considered + // equivalent. + Name HTTPHeaderName `json:"name"` + + // Value is the value of HTTP Header to be matched. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=4096 + Value string `json:"value"` +} + +// HTTPRequestHeaderFilter defines configuration for the RequestHeaderModifier +// filter. +type HTTPRequestHeaderFilter struct { + // Set overwrites the request with the given header (name, value) + // before the action. + // + // Input: + // GET /foo HTTP/1.1 + // my-header: foo + // + // Config: + // set: + // - name: "my-header" + // value: "bar" + // + // Output: + // GET /foo HTTP/1.1 + // my-header: bar + // + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=16 + Set []HTTPHeader `json:"set,omitempty"` + + // Add adds the given header(s) (name, value) to the request + // before the action. It appends to any existing values associated + // with the header name. + // + // Input: + // GET /foo HTTP/1.1 + // my-header: foo + // + // Config: + // add: + // - name: "my-header" + // value: "bar" + // + // Output: + // GET /foo HTTP/1.1 + // my-header: foo + // my-header: bar + // + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=16 + Add []HTTPHeader `json:"add,omitempty"` + + // Remove the given header(s) from the HTTP request before the action. The + // value of Remove is a list of HTTP header names. Note that the header + // names are case-insensitive (see + // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + // + // Input: + // GET /foo HTTP/1.1 + // my-header1: foo + // my-header2: bar + // my-header3: baz + // + // Config: + // remove: ["my-header1", "my-header3"] + // + // Output: + // GET /foo HTTP/1.1 + // my-header2: bar + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Remove []string `json:"remove,omitempty"` +} + +// HTTPPathModifierType defines the type of path redirect or rewrite. +type HTTPPathModifierType string + +const ( + // This type of modifier indicates that the full path will be replaced + // by the specified value. + FullPathHTTPPathModifier HTTPPathModifierType = "ReplaceFullPath" + + // This type of modifier indicates that any prefix path matches will be + // replaced by the substitution value. For example, a path with a prefix + // match of "/foo" and a ReplacePrefixMatch substitution of "/bar" will have + // the "/foo" prefix replaced with "/bar" in matching requests. + PrefixMatchHTTPPathModifier HTTPPathModifierType = "ReplacePrefixMatch" +) + +// HTTPPathModifier defines configuration for path modifiers. +// +type HTTPPathModifier struct { + // Type defines the type of path modifier. Additional types may be + // added in a future release of the API. + // + // + // +kubebuilder:validation:Enum=ReplaceFullPath;ReplacePrefixMatch + Type HTTPPathModifierType `json:"type"` + + // ReplaceFullPath specifies the value with which to replace the full path + // of a request during a rewrite or redirect. + // + // + // +kubebuilder:validation:MaxLength=1024 + // +optional + ReplaceFullPath *string `json:"replaceFullPath,omitempty"` + + // ReplacePrefixMatch specifies the value with which to replace the prefix + // match of a request during a rewrite or redirect. For example, a request + // to "/foo/bar" with a prefix match of "/foo" would be modified to "/bar". + // + // + // +kubebuilder:validation:MaxLength=1024 + // +optional + ReplacePrefixMatch *string `json:"replacePrefixMatch,omitempty"` +} + +// HTTPRequestRedirect defines a filter that redirects a request. This filter +// MUST NOT be used on the same Route rule as a HTTPURLRewrite filter. +type HTTPRequestRedirectFilter struct { + // Scheme is the scheme to be used in the value of the `Location` + // header in the response. + // When empty, the scheme of the request is used. + // + // Support: Extended + // + // +optional + // +kubebuilder:validation:Enum=http;https + Scheme *string `json:"scheme,omitempty"` + + // Hostname is the hostname to be used in the value of the `Location` + // header in the response. + // When empty, the hostname of the request is used. + // + // Support: Core + // + // +optional + Hostname *PreciseHostname `json:"hostname,omitempty"` + + // Path defines parameters used to modify the path of the incoming request. + // The modified path is then used to construct the `Location` header. When + // empty, the request path is used as-is. + // + // Support: Extended + // + // + // +optional + Path *HTTPPathModifier `json:"path,omitempty"` + + // Port is the port to be used in the value of the `Location` + // header in the response. + // When empty, port (if specified) of the request is used. + // + // Support: Extended + // + // +optional + Port *PortNumber `json:"port,omitempty"` + + // StatusCode is the HTTP status code to be used in response. + // + // Support: Core + // + // +optional + // +kubebuilder:default=302 + // +kubebuilder:validation:Enum=301;302 + StatusCode *int `json:"statusCode,omitempty"` +} + +// HTTPURLRewriteFilter defines a filter that modifies a request during +// forwarding. At most one of these filters may be used on a Route rule. This +// MUST NOT be used on the same Route rule as a HTTPRequestRedirect filter. +// +// +// Support: Extended +type HTTPURLRewriteFilter struct { + // Hostname is the value to be used to replace the Host header value during + // forwarding. + // + // Support: Extended + // + // + // +optional + Hostname *PreciseHostname `json:"hostname,omitempty"` + + // Path defines a path rewrite. + // + // Support: Extended + // + // + // +optional + Path *HTTPPathModifier `json:"path,omitempty"` +} + +// HTTPRequestMirrorFilter defines configuration for the RequestMirror filter. +type HTTPRequestMirrorFilter struct { + // BackendRef references a resource where mirrored requests are sent. + // + // If the referent cannot be found, this BackendRef is invalid and must be + // dropped from the Gateway. The controller must ensure the "ResolvedRefs" + // condition on the Route status is set to `status: False` and not configure + // this backend in the underlying implementation. + // + // If there is a cross-namespace reference to an *existing* object + // that is not allowed by a ReferenceGrant, the controller must ensure the + // "ResolvedRefs" condition on the Route is set to `status: False`, + // with the "RefNotPermitted" reason and not configure this backend in the + // underlying implementation. + // + // In either error case, the Message of the `ResolvedRefs` Condition + // should be used to provide more detail about the problem. + // + // Support: Extended for Kubernetes Service + // Support: Custom for any other resource + BackendRef BackendObjectReference `json:"backendRef"` +} + +// HTTPBackendRef defines how a HTTPRoute should forward an HTTP request. +type HTTPBackendRef struct { + // BackendRef is a reference to a backend to forward matched requests to. + // + // If the referent cannot be found, this HTTPBackendRef 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 ReferenceGrant, the controller must ensure the + // "ResolvedRefs" condition on the Route is set to `status: False`, + // with the "RefNotPermitted" reason and not configure this backend in the + // underlying implementation. + // + // In either error case, the Message of the `ResolvedRefs` Condition + // should be used to provide more detail about the problem. + // + // Support: Custom + // + // +optional + BackendRef `json:",inline"` + + // Filters defined at this level should be executed if and only if the + // request is being forwarded to the backend defined here. + // + // Support: Custom (For broader support of filters, use the Filters field + // in HTTPRouteRule.) + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Filters []HTTPRouteFilter `json:"filters,omitempty"` +} + +// HTTPRouteStatus defines the observed state of HTTPRoute. +type HTTPRouteStatus struct { + RouteStatus `json:",inline"` +} diff --git a/apis/v1beta1/object_reference_types.go b/apis/v1beta1/object_reference_types.go new file mode 100644 index 0000000000..ce92bb453d --- /dev/null +++ b/apis/v1beta1/object_reference_types.go @@ -0,0 +1,132 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +// LocalObjectReference identifies an API object within the namespace of the +// referrer. +// The API object must be valid in the cluster; the Group and Kind must +// be registered in the cluster for this reference to be valid. +// +// References to objects with invalid Group and Kind are not valid, and must +// be rejected by the implementation, with appropriate Conditions set +// on the containing object. +type LocalObjectReference struct { + // Group is the group of the referent. For example, "networking.k8s.io". + // When unspecified (empty string), core API group is inferred. + Group Group `json:"group"` + + // Kind is kind of the referent. For example "HTTPRoute" or "Service". + Kind Kind `json:"kind"` + + // Name is the name of the referent. + Name ObjectName `json:"name"` +} + +// SecretObjectReference identifies an API object including its namespace, +// defaulting to Secret. +// +// The API object must be valid in the cluster; the Group and Kind must +// be registered in the cluster for this reference to be valid. +// +// References to objects with invalid Group and Kind are not valid, and must +// be rejected by the implementation, with appropriate Conditions set +// on the containing object. +type SecretObjectReference struct { + // Group is the group of the referent. For example, "networking.k8s.io". + // When unspecified (empty string), core API group is inferred. + // + // +optional + // +kubebuilder:default="" + Group *Group `json:"group"` + + // Kind is kind of the referent. For example "HTTPRoute" or "Service". + // + // +optional + // +kubebuilder:default=Secret + Kind *Kind `json:"kind"` + + // Name is the name of the referent. + Name ObjectName `json:"name"` + + // Namespace is the namespace of the backend. When unspecified, the local + // namespace is inferred. + // + // Note that when a namespace is specified, a ReferenceGrant object + // is required in the referent namespace to allow that namespace's + // owner to accept the reference. See the ReferenceGrant documentation + // for details. + // + // Support: Core + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` +} + +// BackendObjectReference defines how an ObjectReference that is +// specific to BackendRef. It includes a few additional fields and features +// than a regular ObjectReference. +// +// Note that when a namespace is specified, a ReferenceGrant object +// is required in the referent namespace to allow that namespace's +// owner to accept the reference. See the ReferenceGrant documentation +// for details. +// +// The API object must be valid in the cluster; the Group and Kind must +// be registered in the cluster for this reference to be valid. +// +// References to objects with invalid Group and Kind are not valid, and must +// be rejected by the implementation, with appropriate Conditions set +// on the containing object. +type BackendObjectReference struct { + // Group is the group of the referent. For example, "networking.k8s.io". + // When unspecified (empty string), core API group is inferred. + // + // +optional + // +kubebuilder:default="" + Group *Group `json:"group,omitempty"` + + // Kind is kind of the referent. For example "HTTPRoute" or "Service". + // Defaults to "Service" when not specified. + // + // +optional + // +kubebuilder:default=Service + Kind *Kind `json:"kind,omitempty"` + + // Name is the name of the referent. + Name ObjectName `json:"name"` + + // Namespace is the namespace of the backend. When unspecified, the local + // namespace is inferred. + // + // Note that when a namespace is specified, a ReferenceGrant object + // is required in the referent namespace to allow that namespace's + // owner to accept the reference. See the ReferenceGrant documentation + // for details. + // + // Support: Core + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` + + // Port specifies the destination port number to use for this resource. + // Port is required when the referent is a Kubernetes Service. + // For other resources, destination port might be derived from the referent + // resource or this field. + // + // +optional + Port *PortNumber `json:"port,omitempty"` +} diff --git a/apis/v1beta1/shared_types.go b/apis/v1beta1/shared_types.go new file mode 100644 index 0000000000..cb3776e872 --- /dev/null +++ b/apis/v1beta1/shared_types.go @@ -0,0 +1,512 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ParentReference identifies an API object (usually a Gateway) that can be considered +// a parent of this resource (usually a route). 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. +// +// The API object must be valid in the cluster; the Group and Kind must +// be registered in the cluster for this reference to be valid. +type ParentReference struct { + // Group is the group of the referent. + // + // Support: Core + // + // +kubebuilder:default=gateway.networking.k8s.io + // +optional + Group *Group `json:"group,omitempty"` + + // Kind is kind of the referent. + // + // Support: Core (Gateway) + // Support: Custom (Other Resources) + // + // +kubebuilder:default=Gateway + // +optional + Kind *Kind `json:"kind,omitempty"` + + // Namespace is the namespace of the referent. When unspecified (or empty + // string), this refers to the local namespace of the Route. + // + // Support: Core + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` + + // Name is the name of the referent. + // + // Support: Core + Name ObjectName `json:"name"` + + // SectionName is the name of a section within the target resource. In the + // following resources, SectionName is interpreted as the following: + // + // * Gateway: Listener Name. When both Port (experimental) and SectionName + // are specified, the name and port of the selected listener must match + // both specified values. + // + // Implementations MAY choose to support attaching Routes to other resources. + // If that is the case, they MUST clearly document how SectionName is + // interpreted. + // + // When unspecified (empty string), this will reference the entire resource. + // For the purpose of status, an attachment is considered successful if at + // least one section in the parent resource accepts it. For example, Gateway + // listeners can restrict which Routes can attach to them by Route kind, + // namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + // the referencing Route, the Route MUST be considered successfully + // attached. If no Gateway listeners accept attachment from this Route, the + // Route MUST be considered detached from the Gateway. + // + // Support: Core + // + // +optional + SectionName *SectionName `json:"sectionName,omitempty"` + + // Port is the network port this Route targets. It can be interpreted + // differently based on the type of parent resource. + // + // When the parent resource is a Gateway, this targets all listeners + // listening on the specified port that also support this kind of Route(and + // select this Route). It's not recommended to set `Port` unless the + // networking behaviors specified in a Route must apply to a specific port + // as opposed to a listener(s) whose port(s) may be changed. When both Port + // and SectionName are specified, the name and port of the selected listener + // must match both specified values. + // + // Implementations MAY choose to support other parent resources. + // Implementations supporting other types of parent resources MUST clearly + // document how/if Port is interpreted. + // + // For the purpose of status, an attachment is considered successful as + // long as the parent resource accepts it partially. For example, Gateway + // listeners can restrict which Routes can attach to them by Route kind, + // namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + // from the referencing Route, the Route MUST be considered successfully + // attached. If no Gateway listeners accept attachment from this Route, + // the Route MUST be considered detached from the Gateway. + // + // Support: Extended + // + // +optional + // + Port *PortNumber `json:"port,omitempty"` +} + +// CommonRouteSpec defines the common attributes that all Routes MUST include +// within their spec. +type CommonRouteSpec struct { + // ParentRefs references the resources (usually Gateways) that a Route wants + // to be attached to. Note that the referenced parent resource needs to + // allow this for the attachment to be complete. For Gateways, that means + // the Gateway needs to allow attachment from Routes of this kind and + // namespace. + // + // 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. + // + // 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. + // + // 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. + // + // +optional + // +kubebuilder:validation:MaxItems=32 + ParentRefs []ParentReference `json:"parentRefs,omitempty"` +} + +// PortNumber defines a network port. +// +// +kubebuilder:validation:Minimum=1 +// +kubebuilder:validation:Maximum=65535 +type PortNumber int32 + +// BackendRef defines how a Route should forward a request to a Kubernetes +// resource. +// +// Note that when a namespace is specified, a ReferenceGrant object +// is required in the referent namespace to allow that namespace's +// owner to accept the reference. See the ReferenceGrant documentation +// for details. +type BackendRef struct { + // BackendObjectReference references a Kubernetes object. + BackendObjectReference `json:",inline"` + + // Weight specifies the proportion of requests forwarded to the referenced + // backend. This is computed as weight/(sum of all weights in this + // BackendRefs list). For non-zero values, there may be some epsilon from + // the exact proportion defined here depending on the precision an + // implementation supports. Weight is not a percentage and the sum of + // weights does not need to equal 100. + // + // If only one backend is specified and it has a weight greater than 0, 100% + // of the traffic is forwarded to that backend. If weight is set to 0, no + // traffic should be forwarded for this entry. If unspecified, weight + // defaults to 1. + // + // Support for this field varies based on the context where used. + // + // +optional + // +kubebuilder:default=1 + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=1000000 + Weight *int32 `json:"weight,omitempty"` +} + +// RouteConditionType is a type of condition for a route. +type RouteConditionType string + +// RouteConditionReason is a reason for a route condition. +type RouteConditionReason string + +const ( + // This condition indicates whether the route has been accepted or rejected + // by a Gateway, and why. + // + // Possible reasons for this condition to be true are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "NotAllowedByListeners" + // * "NoMatchingListenerHostname" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + RouteConditionAccepted RouteConditionType = "Accepted" + + // This reason is used with the "Accepted" condition when the Route has been + // accepted by the Gateway. + RouteReasonAccepted RouteConditionReason = "Accepted" + + // This reason is used with the "Accepted" condition when the route has not + // been accepted by a Gateway because the Gateway has no Listener whose + // allowedRoutes criteria permit the route + RouteReasonNotAllowedByListeners RouteConditionReason = "NotAllowedByListeners" + + // This reason is used with the "Accepted" condition when the Gateway has no + // compatible Listeners whose Hostname matches the route + RouteReasonNoMatchingListenerHostname RouteConditionReason = "NoMatchingListenerHostname" + + // This condition indicates whether the controller was able to resolve all + // the object references for the Route. + // + // Possible reasons for this condition to be true are: + // + // * "ResolvedRefs" + // + // Possible reasons for this condition to be false are: + // + // * "RefNotPermitted" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + RouteConditionResolvedRefs RouteConditionType = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the condition + // is true. + RouteReasonResolvedRefs RouteConditionReason = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when + // one of the Listener's Routes has a BackendRef to an object in + // another namespace, where the object in the other namespace does + // not have a ReferenceGrant explicitly allowing the reference. + RouteReasonRefNotPermitted RouteConditionReason = "RefNotPermitted" +) + +// RouteParentStatus describes the status of a route with respect to an +// associated Parent. +type RouteParentStatus struct { + // ParentRef corresponds with a ParentRef in the spec that this + // RouteParentStatus struct describes the status of. + ParentRef ParentReference `json:"parentRef"` + + // ControllerName is a domain/path string that indicates the name of the + // controller that wrote this status. This corresponds with the + // controllerName field on GatewayClass. + // + // Example: "example.net/gateway-controller". + // + // The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + // valid Kubernetes names + // (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + // + // Controllers MUST populate this field when writing status. Controllers should ensure that + // entries to status populated with their ControllerName are cleaned up when they are no + // longer necessary. + ControllerName GatewayController `json:"controllerName"` + + // Conditions describes the status of the route with respect to the Gateway. + // Note that the route's availability is also subject to the Gateway's own + // status conditions and listener status. + // + // If the Route's ParentRef specifies an existing Gateway that supports + // Routes of this kind AND that Gateway's controller has sufficient access, + // then that Gateway's controller MUST set the "Accepted" condition on the + // Route, to indicate whether the route has been accepted or rejected by the + // Gateway, and why. + // + // A Route MUST be considered "Accepted" if at least one of the Route's + // rules is implemented by the Gateway. + // + // There are a number of cases where the "Accepted" condition may not be set + // due to lack of controller visibility, that includes when: + // + // * The Route refers to a non-existent parent. + // * The Route is of a type that the controller does not support. + // * The Route is in a namespace the the controller does not have access to. + // + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// RouteStatus defines the common attributes that all Routes MUST include within +// their status. +type RouteStatus struct { + // Parents is a list of parent resources (usually Gateways) that are + // associated with the route, and the status of the route with respect to + // each parent. When this route attaches to a parent, the controller that + // manages the parent must add an entry to this list when the controller + // first sees the route and should update the entry as appropriate when the + // route or gateway is modified. + // + // Note that parent references that cannot be resolved by an implementation + // of this API will not be added to this list. Implementations of this API + // can only populate Route status for the Gateways/parent resources they are + // responsible for. + // + // A maximum of 32 Gateways will be represented in this list. An empty list + // means the route has not been attached to any Gateway. + // + // +kubebuilder:validation:MaxItems=32 + Parents []RouteParentStatus `json:"parents"` +} + +// Hostname is the fully qualified domain name of a network host. This matches +// the RFC 1123 definition of a hostname with 2 notable exceptions: +// +// 1. IPs are not allowed. +// 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard +// label must appear by itself as the first label. +// +// Hostname can be "precise" which is a domain name without the terminating +// dot of a network host (e.g. "foo.example.com") or "wildcard", which is a +// domain name prefixed with a single wildcard label (e.g. `*.example.com`). +// +// Note that as per RFC1035 and RFC1123, a *label* must consist of lower case +// alphanumeric characters or '-', and must start and end with an alphanumeric +// character. No other punctuation is allowed. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +type Hostname string + +// PreciseHostname is the fully qualified domain name of a network host. This +// matches the RFC 1123 definition of a hostname with 1 notable exception that +// numeric IP addresses are not allowed. +// +// Note that as per RFC1035 and RFC1123, a *label* must consist of lower case +// alphanumeric characters or '-', and must start and end with an alphanumeric +// character. No other punctuation is allowed. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +type PreciseHostname string + +// Group refers to a Kubernetes Group. It must either be an empty string or a +// RFC 1123 subdomain. +// +// This validation is based off of the corresponding Kubernetes validation: +// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 +// +// Valid values include: +// +// * "" - empty string implies core Kubernetes API group +// * "networking.k8s.io" +// * "foo.example.com" +// +// Invalid values include: +// +// * "example.com/bar" - "/" is an invalid character +// +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +type Group string + +// Kind refers to a Kubernetes Kind. +// +// Valid values include: +// +// * "Service" +// * "HTTPRoute" +// +// Invalid values include: +// +// * "invalid/kind" - "/" is an invalid character +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=63 +// +kubebuilder:validation:Pattern=`^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` +type Kind string + +// ObjectName refers to the name of a Kubernetes object. +// Object names can have a variety of forms, including RFC1123 subdomains, +// RFC 1123 labels, or RFC 1035 labels. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +type ObjectName string + +// Namespace refers to a Kubernetes namespace. It must be a RFC 1123 label. +// +// This validation is based off of the corresponding Kubernetes validation: +// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L187 +// +// This is used for Namespace name validation here: +// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/api/validation/generic.go#L63 +// +// Valid values include: +// +// * "example" +// +// Invalid values include: +// +// * "example.com" - "." is an invalid character +// +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=63 +type Namespace string + +// SectionName is the name of a section in a Kubernetes resource. +// +// This validation is based off of the corresponding Kubernetes validation: +// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 +// +// Valid values include: +// +// * "example.com" +// * "foo.example.com" +// +// Invalid values include: +// +// * "example.com/bar" - "/" is an invalid character +// +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +type SectionName string + +// GatewayController is the name of a Gateway API controller. It must be a +// domain prefixed path. +// +// Valid values include: +// +// * "example.com/bar" +// +// Invalid values include: +// +// * "example.com" - must include path +// * "foo.example.com" - must include path +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` +type GatewayController string + +// AnnotationKey is the key of an annotation in Gateway API. This is used for +// validation of maps such as TLS options. This matches the Kubernetes +// "qualified name" validation that is used for annotations and other common +// values. +// +// Valid values include: +// +// * example +// * example.com +// * example.com/path +// * example.com/path.html +// +// Invalid values include: +// +// * example~ - "~" is an invalid character +// * example.com. - can not start or end with "." +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]/?)*$` +type AnnotationKey string + +// AnnotationValue is the value of an annotation in Gateway API. This is used +// for validation of maps such as TLS options. This roughly matches Kubernetes +// annotation validation, although the length validation in that case is based +// on the entire size of the annotations struct. +// +// +kubebuilder:validation:MinLength=0 +// +kubebuilder:validation:MaxLength=4096 +type AnnotationValue string + +// AddressType defines how a network address is represented as a text string. +type AddressType string + +const ( + // A textual representation of a numeric IP address. IPv4 + // addresses must be in dotted-decimal form. IPv6 addresses + // must be in a standard IPv6 text representation + // (see [RFC 5952](https://tools.ietf.org/html/rfc5952)). + // + // This type is intended for specific addresses. Address ranges are not + // supported (e.g. you can not use a CIDR range like 127.0.0.0/24 as an + // IPAddress). + // + // Support: Extended + IPAddressType AddressType = "IPAddress" + + // A Hostname represents a DNS based ingress point. This is similar to the + // corresponding hostname field in Kubernetes load balancer status. For + // example, this concept may be used for cloud load balancers where a DNS + // name is used to expose a load balancer. + // + // Support: Extended + HostnameAddressType AddressType = "Hostname" + + // A NamedAddress provides a way to reference a specific IP address by name. + // For example, this may be a name or other unique identifier that refers + // to a resource on a cloud provider such as a static IP. + // + // Support: Implementation-Specific + NamedAddressType AddressType = "NamedAddress" +) diff --git a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml index 5a54547be3..e9a52a5720 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml @@ -24,6 +24,9 @@ spec: - jsonPath: .spec.controllerName name: Controller type: string + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string - jsonPath: .metadata.creationTimestamp name: Age type: date diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 0db2423680..563ea1271d 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -70,7 +70,7 @@ spec: manner, assigning an appropriate set of Addresses. \n The implementation MUST bind all Listeners to every GatewayAddress that it assigns to the Gateway and add a corresponding entry in GatewayStatus.Addresses. - \n Support: Core" + \n Support: Extended" items: description: GatewayAddress describes an address that can be bound to a Gateway. @@ -280,7 +280,11 @@ spec: array. When both listener and route specify hostnames, there MUST be an intersection between the values for a Route to be accepted. For more information, refer to the Route specific - Hostnames documentation. \n Support: Core" + Hostnames documentation. \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 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])?)*$ @@ -327,9 +331,9 @@ spec: MAY choose to support attaching multiple certificates to a Listener, but this behavior is implementation-specific. \n References to a resource in different namespace are - invalid UNLESS there is a ReferencePolicy in the target + invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. - If a ReferencePolicy does not allow this reference, the + If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this listener with the \"InvalidCertificateRef\" reason. \n This field is required to have at least one element when @@ -337,8 +341,9 @@ spec: otherwise. \n CertificateRefs can reference to standard Kubernetes resources, i.e. Secret, or implementation-specific custom resources. \n Support: Core - A single reference - to a Kubernetes Secret \n Support: Implementation-specific - (More than one reference or other resource types)" + to a Kubernetes Secret of type kubernetes.io/tls \n Support: + Implementation-specific (More than one reference or other + resource types)" items: description: "SecretObjectReference identifies an API object including its namespace, defaulting to Secret. @@ -373,10 +378,10 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. - \n Note that when a namespace is specified, a ReferencePolicy + \n Note that when a namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. - See the ReferencePolicy documentation for details. + See the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index de674392ab..4b83a9db1d 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -63,17 +63,21 @@ spec: * A Listener with `*.example.com` as the hostname matches HTTPRoutes \ that have either not specified any hostnames or have specified at least one hostname that matches the Listener hostname. For - example, `test.example.com` and `*.example.com` would both match. - On the other hand, `example.com` and `test.example.net` would - not match. \n If both the Listener and HTTPRoute have specified - hostnames, any HTTPRoute hostnames that do not match the Listener - hostname MUST be ignored. For example, if a Listener specified `*.example.com`, - and the HTTPRoute specified `test.example.com` and `test.example.net`, - `test.example.net` must not be considered for a match. \n If both - the Listener and HTTPRoute have specified hostnames, and none match - with the criteria above, then the HTTPRoute is not accepted. The - implementation must raise an 'Accepted' Condition with a status - of `False` in the corresponding RouteParentStatus. \n Support: Core" + example, `*.example.com`, `test.example.com`, and `foo.test.example.com` + would all match. On the other hand, `example.com` and `test.example.net` + would not match. \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 HTTPRoute have specified hostnames, any HTTPRoute hostnames + that do not match the Listener hostname MUST be ignored. For example, + if a Listener specified `*.example.com`, and the HTTPRoute specified + `test.example.com` and `test.example.net`, `test.example.net` must + not be considered for a match. \n If both the Listener and HTTPRoute + have specified hostnames, and none match with the criteria above, + then the HTTPRoute is not accepted. The implementation must raise + an 'Accepted' Condition with a status of `False` in the corresponding + RouteParentStatus. \n Support: Core" items: description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with @@ -115,10 +119,7 @@ spec: is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. \n - References to objects with invalid Group and Kind are not valid, - and must be rejected by the implementation, with appropriate Conditions - set on the containing object." + be registered in the cluster for this reference to be valid." properties: group: default: gateway.networking.k8s.io @@ -152,25 +153,25 @@ spec: port: description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent - resource: \n * Gateway: 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 " + 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 @@ -216,15 +217,23 @@ spec: and forwarding the request to an API object (backendRefs). properties: backendRefs: - description: "If unspecified or invalid (refers to a non-existent - resource or a Service with no endpoints), the rule performs - no forwarding. If there are also no filters specified that - would result in a response being sent, a HTTP 503 status code - is returned. 503 responses must be sent so that the overall - weight is respected; if an invalid backend is requested to - have 80% of requests, then 80% of requests must get a 503 - instead. \n Support: Core for Kubernetes Service Support: - Custom for any other resource \n Support for weight: Core" + description: "BackendRefs defines the backend(s) where matching + requests should be sent. \n A 404 status code 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, 404 status codes MUST be returned + for requests that would have otherwise been routed to an invalid + backend. If multiple backends are specified, and some are + invalid, the proportion of requests that would otherwise have + been routed to an invalid backend MUST receive a 404 status + code. \n When a BackendRef refers to a Service that has no + ready endpoints, it is recommended to return a 503 status + code. \n Support: Core for Kubernetes Service Support: Custom + for any other resource \n Support for weight: Core" items: description: HTTPBackendRef defines how a HTTPRoute should forward an HTTP request. @@ -402,7 +411,7 @@ spec: False` and not configure this backend in the underlying implementation. \n If there is a cross-namespace reference to an *existing* - object that is not allowed by a ReferencePolicy, + 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 @@ -426,6 +435,7 @@ spec: 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])?$ @@ -439,10 +449,10 @@ spec: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that - when a namespace is specified, a ReferencePolicy + when a namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept - the reference. See the ReferencePolicy + the reference. See the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 @@ -488,26 +498,31 @@ spec: path is used as-is. \n Support: Extended \n " properties: - substitution: - description: "Substitution defines the HTTP - path value to substitute. An empty value - (\"\") indicates that the portion of the - path to be changed should be removed from - the resulting path. For example, a request - to \"/foo/bar\" with a prefix match of - \"/foo\" would be modified to \"/bar\". - \n " + replaceFullPath: + description: "ReplaceFullPath specifies + the value with which to replace the full + path of a request during a rewrite or + redirect. \n " + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies + the value with which to replace the prefix + match of a request during a rewrite or + redirect. For example, a request to \"/foo/bar\" + with a prefix match of \"/foo\" would + be modified to \"/bar\". \n " maxLength: 1024 type: string type: description: "Type defines the type of path - modifier. \n " + modifier. Additional types may be added + in a future release of the API. \n " enum: - - Absolute + - ReplaceFullPath - ReplacePrefixMatch type: string required: - - substitution - type type: object port: @@ -581,32 +596,37 @@ spec: \n Support: Extended \n " maxLength: 253 minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: description: "Path defines a path rewrite. \n Support: Extended \n " properties: - substitution: - description: "Substitution defines the HTTP - path value to substitute. An empty value - (\"\") indicates that the portion of the - path to be changed should be removed from - the resulting path. For example, a request - to \"/foo/bar\" with a prefix match of - \"/foo\" would be modified to \"/bar\". - \n " + replaceFullPath: + description: "ReplaceFullPath specifies + the value with which to replace the full + path of a request during a rewrite or + redirect. \n " + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies + the value with which to replace the prefix + match of a request during a rewrite or + redirect. For example, a request to \"/foo/bar\" + with a prefix match of \"/foo\" would + be modified to \"/bar\". \n " maxLength: 1024 type: string type: description: "Type defines the type of path - modifier. \n " + modifier. Additional types may be added + in a future release of the API. \n " enum: - - Absolute + - ReplaceFullPath - ReplacePrefixMatch type: string required: - - substitution - type type: object type: object @@ -626,7 +646,8 @@ spec: kind: default: Service description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + "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])?$ @@ -639,10 +660,10 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy + Note that when a namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: + the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 @@ -851,7 +872,7 @@ spec: is set to `status: False` and not configure this backend in the underlying implementation. \n If there is a cross-namespace reference to an *existing* - object that is not allowed by a ReferencePolicy, + 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 @@ -872,7 +893,8 @@ spec: kind: default: Service description: Kind is kind of the referent. For - example "HTTPRoute" or "Service". + 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])?$ @@ -886,9 +908,9 @@ spec: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace is - specified, a ReferencePolicy object is required + specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's - owner to accept the reference. See the ReferencePolicy + owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 @@ -931,25 +953,30 @@ spec: When empty, the request path is used as-is. \n Support: Extended \n " properties: - substitution: - description: "Substitution defines the HTTP path - value to substitute. An empty value (\"\") indicates - that the portion of the path to be changed should - be removed from the resulting path. For example, - a request to \"/foo/bar\" with a prefix match - of \"/foo\" would be modified to \"/bar\". \n - " + replaceFullPath: + description: "ReplaceFullPath specifies the value + with which to replace the full path of a request + during a rewrite or redirect. \n " + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the + value with which to replace the prefix match + of a request during a rewrite or redirect. For + example, a request to \"/foo/bar\" with a prefix + match of \"/foo\" would be modified to \"/bar\". + \n " maxLength: 1024 type: string type: description: "Type defines the type of path modifier. - \n " + Additional types may be added in a future release + of the API. \n " enum: - - Absolute + - ReplaceFullPath - ReplacePrefixMatch type: string required: - - substitution - type type: object port: @@ -1021,31 +1048,36 @@ spec: \n Support: Extended \n " maxLength: 253 minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: description: "Path defines a path rewrite. \n Support: Extended \n " properties: - substitution: - description: "Substitution defines the HTTP path - value to substitute. An empty value (\"\") indicates - that the portion of the path to be changed should - be removed from the resulting path. For example, - a request to \"/foo/bar\" with a prefix match - of \"/foo\" would be modified to \"/bar\". \n - " + replaceFullPath: + description: "ReplaceFullPath specifies the value + with which to replace the full path of a request + during a rewrite or redirect. \n " + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the + value with which to replace the prefix match + of a request during a rewrite or redirect. For + example, a request to \"/foo/bar\" with a prefix + match of \"/foo\" would be modified to \"/bar\". + \n " maxLength: 1024 type: string type: description: "Type defines the type of path modifier. - \n " + Additional types may be added in a future release + of the API. \n " enum: - - Absolute + - ReplaceFullPath - ReplacePrefixMatch type: string required: - - substitution - type type: object type: object @@ -1085,7 +1117,9 @@ spec: 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." + rule meeting the above criteria. \n When no rules matching + a request have been successfully attached to the parent a + request is coming from, a HTTP 404 status code MUST be returned." items: description: "HTTPRouteMatch defines the predicate used to match requests to a given action. Multiple match types are @@ -1365,7 +1399,11 @@ spec: 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)." + 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\/\-._~%!$&'()*+,;=:]+$ @@ -1406,24 +1444,25 @@ spec: port: description: "Port is the network port this Route targets. It can be interpreted differently based on the type of - parent resource: \n * Gateway: 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, + 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 diff --git a/config/crd/experimental/gateway.networking.k8s.io_referencepolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml similarity index 90% rename from config/crd/experimental/gateway.networking.k8s.io_referencepolicies.yaml rename to config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml index 74736cf74c..d3511539da 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_referencepolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml @@ -6,18 +6,18 @@ metadata: gateway.networking.k8s.io/bundle-version: v0.5.0-dev gateway.networking.k8s.io/channel: experimental creationTimestamp: null - name: referencepolicies.gateway.networking.k8s.io + name: referencegrants.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - gateway-api - kind: ReferencePolicy - listKind: ReferencePolicyList - plural: referencepolicies + kind: ReferenceGrant + listKind: ReferenceGrantList + plural: referencegrants shortNames: - refpol - singular: referencepolicy + singular: referencegrant scope: Namespaced versions: - additionalPrinterColumns: @@ -27,14 +27,14 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: "ReferencePolicy identifies kinds of resources in other namespaces + description: "ReferenceGrant identifies kinds of resources in other namespaces that are trusted to reference the specified kinds of resources in the same - namespace as the policy. \n Each ReferencePolicy can be used to represent + namespace as the policy. \n Each ReferenceGrant can be used to represent a unique trust relationship. Additional Reference Policies can be used to add to the set of trusted sources of inbound references for the namespace they are defined within. \n All cross-namespace references in Gateway API (with the exception of cross-namespace Gateway-route attachment) require - a ReferencePolicy. \n Support: Core" + a ReferenceGrant. \n Support: Core" properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -49,7 +49,7 @@ spec: metadata: type: object spec: - description: Spec defines the desired state of ReferencePolicy. + description: Spec defines the desired state of ReferenceGrant. properties: from: description: "From describes the trusted namespaces and kinds that @@ -58,7 +58,7 @@ spec: can be valid from, or to put this another way, entries must be combined using OR. \n Support: Core" items: - description: ReferencePolicyFrom describes trusted namespaces and + description: ReferenceGrantFrom describes trusted namespaces and kinds. properties: group: @@ -98,8 +98,8 @@ spec: to, or to put this another way, entries must be combined using OR. \n Support: Core" items: - description: ReferencePolicyTo describes what Kinds are allowed - as targets of the references. + description: ReferenceGrantTo describes what Kinds are allowed as + targets of the references. properties: group: description: "Group is the group of the referent. When empty, diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index 264476524a..d65eacd0bf 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -67,10 +67,7 @@ spec: is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. \n - References to objects with invalid Group and Kind are not valid, - and must be rejected by the implementation, with appropriate Conditions - set on the containing object." + be registered in the cluster for this reference to be valid." properties: group: default: gateway.networking.k8s.io @@ -104,25 +101,25 @@ spec: port: description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent - resource: \n * Gateway: 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 " + 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 @@ -173,9 +170,9 @@ spec: items: description: "BackendRef defines how a Route should forward a request to a Kubernetes resource. \n Note that when a - namespace is specified, a ReferencePolicy object is required + namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner - to accept the reference. See the ReferencePolicy documentation + to accept the reference. See the ReferenceGrant documentation for details." properties: group: @@ -189,7 +186,8 @@ spec: kind: default: Service description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + "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])?$ @@ -202,10 +200,10 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy + Note that when a namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: + the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 @@ -246,94 +244,6 @@ spec: maxItems: 16 minItems: 1 type: array - matches: - description: "Matches are rules for routing traffic to backends - based on addresses. \n " - items: - description: AddressRouteMatches defines AddressMatch rules - for inbound traffic according to source and/or destination - address of a packet or connection. - properties: - destinationAddresses: - description: "DestinationAddresses indicates the destination - network addresses which are valid for routing traffic. - \n Support: Extended" - items: - description: AddressMatch defines matching rules for - network addresses by type. - properties: - type: - default: IPAddress - description: "Type of the address, either IPAddress - or NamedAddress. \n If NamedAddress is used this - is a custom and specific value for each implementation - to handle (and add validation for) according to - their own needs. \n For IPAddress the implementor - may expect either IPv4 or IPv6. \n Support: Core - (IPAddress) Support: Custom (NamedAddress)" - enum: - - IPAddress - - NamedAddress - type: string - value: - description: "Value of the address. The validity - of the values will depend on the type and support - by the controller. \n If implementations support - proxy-protocol (see: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) - they must respect the connection metadata from - proxy-protocol in the match logic implemented - for these address values. \n Examples: `1.2.3.4`, - `128::1`, `my-named-address`. \n Support: Core" - maxLength: 253 - minLength: 1 - type: string - required: - - value - type: object - type: array - sourceAddresses: - description: "SourceAddresses indicates the originating - (source) network addresses which are valid for routing - traffic. \n Support: Extended" - items: - description: AddressMatch defines matching rules for - network addresses by type. - properties: - type: - default: IPAddress - description: "Type of the address, either IPAddress - or NamedAddress. \n If NamedAddress is used this - is a custom and specific value for each implementation - to handle (and add validation for) according to - their own needs. \n For IPAddress the implementor - may expect either IPv4 or IPv6. \n Support: Core - (IPAddress) Support: Custom (NamedAddress)" - enum: - - IPAddress - - NamedAddress - type: string - value: - description: "Value of the address. The validity - of the values will depend on the type and support - by the controller. \n If implementations support - proxy-protocol (see: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) - they must respect the connection metadata from - proxy-protocol in the match logic implemented - for these address values. \n Examples: `1.2.3.4`, - `128::1`, `my-named-address`. \n Support: Core" - maxLength: 253 - minLength: 1 - type: string - required: - - value - type: object - type: array - required: - - destinationAddresses - - sourceAddresses - type: object - maxItems: 16 - type: array type: object maxItems: 16 minItems: 1 @@ -461,7 +371,11 @@ spec: 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)." + 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\/\-._~%!$&'()*+,;=:]+$ @@ -502,24 +416,25 @@ spec: port: description: "Port is the network port this Route targets. It can be interpreted differently based on the type of - parent resource: \n * Gateway: 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, + 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 diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index feb0ad9065..6acbeca272 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -113,10 +113,7 @@ spec: is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. \n - References to objects with invalid Group and Kind are not valid, - and must be rejected by the implementation, with appropriate Conditions - set on the containing object." + be registered in the cluster for this reference to be valid." properties: group: default: gateway.networking.k8s.io @@ -150,25 +147,25 @@ spec: port: description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent - resource: \n * Gateway: 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 " + 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 @@ -213,7 +210,7 @@ spec: the rule performs no forwarding; if no filters are specified that would result in a response being sent, the underlying implementation must actively reject request attempts to this - backend, by rejecting the connection or returning a 503 status + backend, by rejecting the connection or returning a 404 status code. Request rejections must respect weight; if an invalid backend is requested to have 80% of requests, then 80% of requests must be rejected instead. \n Support: Core for Kubernetes @@ -222,9 +219,9 @@ spec: items: description: "BackendRef defines how a Route should forward a request to a Kubernetes resource. \n Note that when a - namespace is specified, a ReferencePolicy object is required + namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner - to accept the reference. See the ReferencePolicy documentation + to accept the reference. See the ReferenceGrant documentation for details." properties: group: @@ -238,7 +235,8 @@ spec: kind: default: Service description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + "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])?$ @@ -251,10 +249,10 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy + Note that when a namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: + the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 @@ -422,7 +420,11 @@ spec: 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)." + 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\/\-._~%!$&'()*+,;=:]+$ @@ -463,24 +465,25 @@ spec: port: description: "Port is the network port this Route targets. It can be interpreted differently based on the type of - parent resource: \n * Gateway: 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, + 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 diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index 322cd8f467..d38bd917e2 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -67,10 +67,7 @@ spec: is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. \n - References to objects with invalid Group and Kind are not valid, - and must be rejected by the implementation, with appropriate Conditions - set on the containing object." + be registered in the cluster for this reference to be valid." properties: group: default: gateway.networking.k8s.io @@ -104,25 +101,25 @@ spec: port: description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent - resource: \n * Gateway: 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 " + 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 @@ -173,9 +170,9 @@ spec: items: description: "BackendRef defines how a Route should forward a request to a Kubernetes resource. \n Note that when a - namespace is specified, a ReferencePolicy object is required + namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner - to accept the reference. See the ReferencePolicy documentation + to accept the reference. See the ReferenceGrant documentation for details." properties: group: @@ -189,7 +186,8 @@ spec: kind: default: Service description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + "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])?$ @@ -202,10 +200,10 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy + Note that when a namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: + the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 @@ -246,94 +244,6 @@ spec: maxItems: 16 minItems: 1 type: array - matches: - description: "Matches add rules for filtering traffic to backends - based on addresses. \n " - items: - description: AddressRouteMatches defines AddressMatch rules - for inbound traffic according to source and/or destination - address of a packet or connection. - properties: - destinationAddresses: - description: "DestinationAddresses indicates the destination - network addresses which are valid for routing traffic. - \n Support: Extended" - items: - description: AddressMatch defines matching rules for - network addresses by type. - properties: - type: - default: IPAddress - description: "Type of the address, either IPAddress - or NamedAddress. \n If NamedAddress is used this - is a custom and specific value for each implementation - to handle (and add validation for) according to - their own needs. \n For IPAddress the implementor - may expect either IPv4 or IPv6. \n Support: Core - (IPAddress) Support: Custom (NamedAddress)" - enum: - - IPAddress - - NamedAddress - type: string - value: - description: "Value of the address. The validity - of the values will depend on the type and support - by the controller. \n If implementations support - proxy-protocol (see: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) - they must respect the connection metadata from - proxy-protocol in the match logic implemented - for these address values. \n Examples: `1.2.3.4`, - `128::1`, `my-named-address`. \n Support: Core" - maxLength: 253 - minLength: 1 - type: string - required: - - value - type: object - type: array - sourceAddresses: - description: "SourceAddresses indicates the originating - (source) network addresses which are valid for routing - traffic. \n Support: Extended" - items: - description: AddressMatch defines matching rules for - network addresses by type. - properties: - type: - default: IPAddress - description: "Type of the address, either IPAddress - or NamedAddress. \n If NamedAddress is used this - is a custom and specific value for each implementation - to handle (and add validation for) according to - their own needs. \n For IPAddress the implementor - may expect either IPv4 or IPv6. \n Support: Core - (IPAddress) Support: Custom (NamedAddress)" - enum: - - IPAddress - - NamedAddress - type: string - value: - description: "Value of the address. The validity - of the values will depend on the type and support - by the controller. \n If implementations support - proxy-protocol (see: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) - they must respect the connection metadata from - proxy-protocol in the match logic implemented - for these address values. \n Examples: `1.2.3.4`, - `128::1`, `my-named-address`. \n Support: Core" - maxLength: 253 - minLength: 1 - type: string - required: - - value - type: object - type: array - required: - - destinationAddresses - - sourceAddresses - type: object - maxItems: 16 - type: array type: object maxItems: 16 minItems: 1 @@ -461,7 +371,11 @@ spec: 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)." + 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\/\-._~%!$&'()*+,;=:]+$ @@ -502,24 +416,25 @@ spec: port: description: "Port is the network port this Route targets. It can be interpreted differently based on the type of - parent resource: \n * Gateway: 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, + 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 diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index eac5f241e1..197fc9ef9b 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -2,7 +2,7 @@ resources: - stable/gateway.networking.k8s.io_gatewayclasses.yaml - stable/gateway.networking.k8s.io_gateways.yaml - stable/gateway.networking.k8s.io_httproutes.yaml -- stable/gateway.networking.k8s.io_referencepolicies.yaml +- stable/gateway.networking.k8s.io_referencegrants.yaml - stable/gateway.networking.k8s.io_tcproutes.yaml - stable/gateway.networking.k8s.io_tlsroutes.yaml - stable/gateway.networking.k8s.io_udproutes.yaml diff --git a/config/crd/stable/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/stable/gateway.networking.k8s.io_gatewayclasses.yaml index 7abaef5028..e52b1f9d30 100644 --- a/config/crd/stable/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/stable/gateway.networking.k8s.io_gatewayclasses.yaml @@ -24,6 +24,9 @@ spec: - jsonPath: .spec.controllerName name: Controller type: string + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string - jsonPath: .metadata.creationTimestamp name: Age type: date diff --git a/config/crd/stable/gateway.networking.k8s.io_gateways.yaml b/config/crd/stable/gateway.networking.k8s.io_gateways.yaml index b7b9813b83..de0070c2d8 100644 --- a/config/crd/stable/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/stable/gateway.networking.k8s.io_gateways.yaml @@ -70,7 +70,7 @@ spec: manner, assigning an appropriate set of Addresses. \n The implementation MUST bind all Listeners to every GatewayAddress that it assigns to the Gateway and add a corresponding entry in GatewayStatus.Addresses. - \n Support: Core" + \n Support: Extended" items: description: GatewayAddress describes an address that can be bound to a Gateway. @@ -280,7 +280,11 @@ spec: array. When both listener and route specify hostnames, there MUST be an intersection between the values for a Route to be accepted. For more information, refer to the Route specific - Hostnames documentation. \n Support: Core" + Hostnames documentation. \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 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])?)*$ @@ -327,9 +331,9 @@ spec: MAY choose to support attaching multiple certificates to a Listener, but this behavior is implementation-specific. \n References to a resource in different namespace are - invalid UNLESS there is a ReferencePolicy in the target + invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. - If a ReferencePolicy does not allow this reference, the + If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this listener with the \"InvalidCertificateRef\" reason. \n This field is required to have at least one element when @@ -337,8 +341,9 @@ spec: otherwise. \n CertificateRefs can reference to standard Kubernetes resources, i.e. Secret, or implementation-specific custom resources. \n Support: Core - A single reference - to a Kubernetes Secret \n Support: Implementation-specific - (More than one reference or other resource types)" + to a Kubernetes Secret of type kubernetes.io/tls \n Support: + Implementation-specific (More than one reference or other + resource types)" items: description: "SecretObjectReference identifies an API object including its namespace, defaulting to Secret. @@ -373,10 +378,10 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. - \n Note that when a namespace is specified, a ReferencePolicy + \n Note that when a namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. - See the ReferencePolicy documentation for details. + See the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 diff --git a/config/crd/stable/gateway.networking.k8s.io_httproutes.yaml b/config/crd/stable/gateway.networking.k8s.io_httproutes.yaml index 36a837b913..9c5aefa395 100644 --- a/config/crd/stable/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/stable/gateway.networking.k8s.io_httproutes.yaml @@ -63,17 +63,21 @@ spec: * A Listener with `*.example.com` as the hostname matches HTTPRoutes \ that have either not specified any hostnames or have specified at least one hostname that matches the Listener hostname. For - example, `test.example.com` and `*.example.com` would both match. - On the other hand, `example.com` and `test.example.net` would - not match. \n If both the Listener and HTTPRoute have specified - hostnames, any HTTPRoute hostnames that do not match the Listener - hostname MUST be ignored. For example, if a Listener specified `*.example.com`, - and the HTTPRoute specified `test.example.com` and `test.example.net`, - `test.example.net` must not be considered for a match. \n If both - the Listener and HTTPRoute have specified hostnames, and none match - with the criteria above, then the HTTPRoute is not accepted. The - implementation must raise an 'Accepted' Condition with a status - of `False` in the corresponding RouteParentStatus. \n Support: Core" + example, `*.example.com`, `test.example.com`, and `foo.test.example.com` + would all match. On the other hand, `example.com` and `test.example.net` + would not match. \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 HTTPRoute have specified hostnames, any HTTPRoute hostnames + that do not match the Listener hostname MUST be ignored. For example, + if a Listener specified `*.example.com`, and the HTTPRoute specified + `test.example.com` and `test.example.net`, `test.example.net` must + not be considered for a match. \n If both the Listener and HTTPRoute + have specified hostnames, and none match with the criteria above, + then the HTTPRoute is not accepted. The implementation must raise + an 'Accepted' Condition with a status of `False` in the corresponding + RouteParentStatus. \n Support: Core" items: description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with @@ -115,10 +119,7 @@ spec: is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. \n - References to objects with invalid Group and Kind are not valid, - and must be rejected by the implementation, with appropriate Conditions - set on the containing object." + be registered in the cluster for this reference to be valid." properties: group: default: gateway.networking.k8s.io @@ -190,15 +191,23 @@ spec: and forwarding the request to an API object (backendRefs). properties: backendRefs: - description: "If unspecified or invalid (refers to a non-existent - resource or a Service with no endpoints), the rule performs - no forwarding. If there are also no filters specified that - would result in a response being sent, a HTTP 503 status code - is returned. 503 responses must be sent so that the overall - weight is respected; if an invalid backend is requested to - have 80% of requests, then 80% of requests must get a 503 - instead. \n Support: Core for Kubernetes Service Support: - Custom for any other resource \n Support for weight: Core" + description: "BackendRefs defines the backend(s) where matching + requests should be sent. \n A 404 status code 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, 404 status codes MUST be returned + for requests that would have otherwise been routed to an invalid + backend. If multiple backends are specified, and some are + invalid, the proportion of requests that would otherwise have + been routed to an invalid backend MUST receive a 404 status + code. \n When a BackendRef refers to a Service that has no + ready endpoints, it is recommended to return a 503 status + code. \n Support: Core for Kubernetes Service Support: Custom + for any other resource \n Support for weight: Core" items: description: HTTPBackendRef defines how a HTTPRoute should forward an HTTP request. @@ -376,7 +385,7 @@ spec: False` and not configure this backend in the underlying implementation. \n If there is a cross-namespace reference to an *existing* - object that is not allowed by a ReferencePolicy, + 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 @@ -400,6 +409,7 @@ spec: 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])?$ @@ -413,10 +423,10 @@ spec: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that - when a namespace is specified, a ReferencePolicy + when a namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept - the reference. See the ReferencePolicy + the reference. See the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 @@ -529,7 +539,8 @@ spec: kind: default: Service description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + "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])?$ @@ -542,10 +553,10 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy + Note that when a namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: + the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 @@ -754,7 +765,7 @@ spec: is set to `status: False` and not configure this backend in the underlying implementation. \n If there is a cross-namespace reference to an *existing* - object that is not allowed by a ReferencePolicy, + 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 @@ -775,7 +786,8 @@ spec: kind: default: Service description: Kind is kind of the referent. For - example "HTTPRoute" or "Service". + 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])?$ @@ -789,9 +801,9 @@ spec: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace is - specified, a ReferencePolicy object is required + specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's - owner to accept the reference. See the ReferencePolicy + owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 @@ -920,7 +932,9 @@ spec: 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." + rule meeting the above criteria. \n When no rules matching + a request have been successfully attached to the parent a + request is coming from, a HTTP 404 status code MUST be returned." items: description: "HTTPRouteMatch defines the predicate used to match requests to a given action. Multiple match types are @@ -1200,7 +1214,11 @@ spec: 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)." + 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\/\-._~%!$&'()*+,;=:]+$ diff --git a/config/crd/stable/gateway.networking.k8s.io_referencepolicies.yaml b/config/crd/stable/gateway.networking.k8s.io_referencegrants.yaml similarity index 90% rename from config/crd/stable/gateway.networking.k8s.io_referencepolicies.yaml rename to config/crd/stable/gateway.networking.k8s.io_referencegrants.yaml index 508dfaa178..6fa5f8d280 100644 --- a/config/crd/stable/gateway.networking.k8s.io_referencepolicies.yaml +++ b/config/crd/stable/gateway.networking.k8s.io_referencegrants.yaml @@ -6,18 +6,18 @@ metadata: gateway.networking.k8s.io/bundle-version: v0.5.0-dev gateway.networking.k8s.io/channel: stable creationTimestamp: null - name: referencepolicies.gateway.networking.k8s.io + name: referencegrants.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - gateway-api - kind: ReferencePolicy - listKind: ReferencePolicyList - plural: referencepolicies + kind: ReferenceGrant + listKind: ReferenceGrantList + plural: referencegrants shortNames: - refpol - singular: referencepolicy + singular: referencegrant scope: Namespaced versions: - additionalPrinterColumns: @@ -27,14 +27,14 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: "ReferencePolicy identifies kinds of resources in other namespaces + description: "ReferenceGrant identifies kinds of resources in other namespaces that are trusted to reference the specified kinds of resources in the same - namespace as the policy. \n Each ReferencePolicy can be used to represent + namespace as the policy. \n Each ReferenceGrant can be used to represent a unique trust relationship. Additional Reference Policies can be used to add to the set of trusted sources of inbound references for the namespace they are defined within. \n All cross-namespace references in Gateway API (with the exception of cross-namespace Gateway-route attachment) require - a ReferencePolicy. \n Support: Core" + a ReferenceGrant. \n Support: Core" properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -49,7 +49,7 @@ spec: metadata: type: object spec: - description: Spec defines the desired state of ReferencePolicy. + description: Spec defines the desired state of ReferenceGrant. properties: from: description: "From describes the trusted namespaces and kinds that @@ -58,7 +58,7 @@ spec: can be valid from, or to put this another way, entries must be combined using OR. \n Support: Core" items: - description: ReferencePolicyFrom describes trusted namespaces and + description: ReferenceGrantFrom describes trusted namespaces and kinds. properties: group: @@ -98,8 +98,8 @@ spec: to, or to put this another way, entries must be combined using OR. \n Support: Core" items: - description: ReferencePolicyTo describes what Kinds are allowed - as targets of the references. + description: ReferenceGrantTo describes what Kinds are allowed as + targets of the references. properties: group: description: "Group is the group of the referent. When empty, diff --git a/config/crd/stable/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/stable/gateway.networking.k8s.io_tcproutes.yaml index f0f0afb610..d643b08ac7 100644 --- a/config/crd/stable/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/stable/gateway.networking.k8s.io_tcproutes.yaml @@ -67,10 +67,7 @@ spec: is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. \n - References to objects with invalid Group and Kind are not valid, - and must be rejected by the implementation, with appropriate Conditions - set on the containing object." + be registered in the cluster for this reference to be valid." properties: group: default: gateway.networking.k8s.io @@ -147,9 +144,9 @@ spec: items: description: "BackendRef defines how a Route should forward a request to a Kubernetes resource. \n Note that when a - namespace is specified, a ReferencePolicy object is required + namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner - to accept the reference. See the ReferencePolicy documentation + to accept the reference. See the ReferenceGrant documentation for details." properties: group: @@ -163,7 +160,8 @@ spec: kind: default: Service description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + "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])?$ @@ -176,10 +174,10 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy + Note that when a namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: + the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 @@ -347,7 +345,11 @@ spec: 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)." + 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\/\-._~%!$&'()*+,;=:]+$ diff --git a/config/crd/stable/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/stable/gateway.networking.k8s.io_tlsroutes.yaml index 58674e15ba..671abd0d1a 100644 --- a/config/crd/stable/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/stable/gateway.networking.k8s.io_tlsroutes.yaml @@ -113,10 +113,7 @@ spec: is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. \n - References to objects with invalid Group and Kind are not valid, - and must be rejected by the implementation, with appropriate Conditions - set on the containing object." + be registered in the cluster for this reference to be valid." properties: group: default: gateway.networking.k8s.io @@ -187,7 +184,7 @@ spec: the rule performs no forwarding; if no filters are specified that would result in a response being sent, the underlying implementation must actively reject request attempts to this - backend, by rejecting the connection or returning a 503 status + backend, by rejecting the connection or returning a 404 status code. Request rejections must respect weight; if an invalid backend is requested to have 80% of requests, then 80% of requests must be rejected instead. \n Support: Core for Kubernetes @@ -196,9 +193,9 @@ spec: items: description: "BackendRef defines how a Route should forward a request to a Kubernetes resource. \n Note that when a - namespace is specified, a ReferencePolicy object is required + namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner - to accept the reference. See the ReferencePolicy documentation + to accept the reference. See the ReferenceGrant documentation for details." properties: group: @@ -212,7 +209,8 @@ spec: kind: default: Service description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + "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])?$ @@ -225,10 +223,10 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy + Note that when a namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: + the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 @@ -396,7 +394,11 @@ spec: 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)." + 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\/\-._~%!$&'()*+,;=:]+$ diff --git a/config/crd/stable/gateway.networking.k8s.io_udproutes.yaml b/config/crd/stable/gateway.networking.k8s.io_udproutes.yaml index 3b254a0326..80cf52e4ae 100644 --- a/config/crd/stable/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/stable/gateway.networking.k8s.io_udproutes.yaml @@ -67,10 +67,7 @@ spec: is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. \n - References to objects with invalid Group and Kind are not valid, - and must be rejected by the implementation, with appropriate Conditions - set on the containing object." + be registered in the cluster for this reference to be valid." properties: group: default: gateway.networking.k8s.io @@ -147,9 +144,9 @@ spec: items: description: "BackendRef defines how a Route should forward a request to a Kubernetes resource. \n Note that when a - namespace is specified, a ReferencePolicy object is required + namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner - to accept the reference. See the ReferencePolicy documentation + to accept the reference. See the ReferenceGrant documentation for details." properties: group: @@ -163,7 +160,8 @@ spec: kind: default: Service description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + "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])?$ @@ -176,10 +174,10 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy + Note that when a namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: + the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 @@ -347,7 +345,11 @@ spec: 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)." + 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\/\-._~%!$&'()*+,;=:]+$ diff --git a/deploy/admission_webhook.yaml b/config/webhook/admission_webhook.yaml similarity index 99% rename from deploy/admission_webhook.yaml rename to config/webhook/admission_webhook.yaml index d67b2c9a2d..6606314025 100644 --- a/deploy/admission_webhook.yaml +++ b/config/webhook/admission_webhook.yaml @@ -30,7 +30,6 @@ kind: Service metadata: labels: name: gateway-api-webhook-server - version: 0.0.1 name: gateway-api-admission-server namespace: gateway-system spec: diff --git a/deploy/certificate_config.yaml b/config/webhook/certificate_config.yaml similarity index 100% rename from deploy/certificate_config.yaml rename to config/webhook/certificate_config.yaml diff --git a/conformance/base/manifests.yaml b/conformance/base/manifests.yaml index e08a9b4ad4..82c28753ca 100644 --- a/conformance/base/manifests.yaml +++ b/conformance/base/manifests.yaml @@ -154,6 +154,52 @@ spec: cpu: 10m --- apiVersion: v1 +kind: Service +metadata: + name: infra-backend-v3 + namespace: gateway-conformance-infra +spec: + selector: + app: infra-backend-v3 + ports: + - protocol: TCP + port: 8080 + targetPort: 3000 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: infra-backend-v3 + namespace: gateway-conformance-infra + labels: + app: infra-backend-v3 +spec: + replicas: 2 + selector: + matchLabels: + app: infra-backend-v3 + template: + metadata: + labels: + app: infra-backend-v3 + spec: + containers: + - name: infra-backend-v3 + image: k8s.gcr.io/ingressconformance/echoserver:v0.0.1 + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + resources: + requests: + cpu: 10m +--- +apiVersion: v1 kind: Namespace metadata: name: gateway-conformance-app-backend diff --git a/conformance/conformance_test.go b/conformance/conformance_test.go index 70fa99760f..e5a1a52ca8 100644 --- a/conformance/conformance_test.go +++ b/conformance/conformance_test.go @@ -18,11 +18,11 @@ limitations under the License. package conformance_test import ( - "flag" "testing" "sigs.k8s.io/gateway-api/apis/v1alpha2" "sigs.k8s.io/gateway-api/conformance/tests" + "sigs.k8s.io/gateway-api/conformance/utils/flags" "sigs.k8s.io/gateway-api/conformance/utils/suite" _ "k8s.io/client-go/plugin/pkg/client/auth" @@ -30,10 +30,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/config" ) -var gatewayClassName = flag.String("gateway-class", "gateway-conformance", "Name of GatewayClass to use for tests") -var showDebug = flag.Bool("debug", false, "Whether to print debug logs") -var shouldCleanup = flag.Bool("cleanup", true, "Whether to cleanup base resources") - func TestConformance(t *testing.T) { cfg, err := config.GetConfig() if err != nil { @@ -45,13 +41,16 @@ func TestConformance(t *testing.T) { } v1alpha2.AddToScheme(client.Scheme()) - t.Logf("Running conformance tests with %s GatewayClass", *gatewayClassName) + t.Logf("Running conformance tests with %s GatewayClass", *flags.GatewayClassName) cSuite := suite.New(suite.Options{ - Client: client, - GatewayClassName: *gatewayClassName, - Debug: *showDebug, - Cleanup: *shouldCleanup, + Client: client, + GatewayClassName: *flags.GatewayClassName, + Debug: *flags.ShowDebug, + CleanupBaseResources: *flags.CleanupBaseResources, + SupportedFeatures: []suite.SupportedFeature{ + suite.SupportReferenceGrant, + }, }) cSuite.Setup(t) cSuite.Run(t, tests.ConformanceTests) diff --git a/conformance/tests/httproute-cross-namespace.go b/conformance/tests/httproute-cross-namespace.go index 044114ca20..a645437ec9 100644 --- a/conformance/tests/httproute-cross-namespace.go +++ b/conformance/tests/httproute-cross-namespace.go @@ -17,15 +17,12 @@ limitations under the License. package tests import ( - "net/url" "testing" - "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" - "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -43,19 +40,8 @@ var HTTPRouteCrossNamespace = suite.ConformanceTest{ gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeReady(t, suite.Client, suite.ControllerName, gwNN, routeNN) t.Run("Simple HTTP request should reach web-backend", func(t *testing.T) { - t.Logf("Making request to http://%s", gwAddr) - cReq, cRes, err := suite.RoundTripper.CaptureRoundTrip(roundtripper.Request{ - URL: url.URL{Scheme: "http", Host: gwAddr}, - Protocol: "HTTP", - }) - - require.NoErrorf(t, err, "error making request") - - http.ExpectResponse(t, cReq, cRes, http.ExpectedResponse{ - Request: http.ExpectedRequest{ - Method: "GET", - Path: "/", - }, + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, gwAddr, http.ExpectedResponse{ + Request: http.ExpectedRequest{Path: "/"}, StatusCode: 200, Backend: "web-backend", Namespace: "gateway-conformance-web-backend", diff --git a/conformance/tests/httproute-invalid-cross-namespace.go b/conformance/tests/httproute-disallowed-kind.go similarity index 64% rename from conformance/tests/httproute-invalid-cross-namespace.go rename to conformance/tests/httproute-disallowed-kind.go index 192b06bdd1..8fc0803b9a 100644 --- a/conformance/tests/httproute-invalid-cross-namespace.go +++ b/conformance/tests/httproute-disallowed-kind.go @@ -29,23 +29,23 @@ import ( ) func init() { - ConformanceTests = append(ConformanceTests, HTTPRouteInvalidCrossNamespace) + ConformanceTests = append(ConformanceTests, HTTPRouteDisallowedKind) } -var HTTPRouteInvalidCrossNamespace = suite.ConformanceTest{ - ShortName: "HTTPRouteInvalidCrossNamespace", - Description: "A single HTTPRoute in the gateway-conformance-web-backend namespace should fail to attach to a Gateway in another namespace that it is not allowed to", - Manifests: []string{"tests/httproute-invalid-cross-namespace.yaml"}, +var HTTPRouteDisallowedKind = suite.ConformanceTest{ + ShortName: "HTTPRouteDisallowedKind", + Description: "A single HTTPRoute in the gateway-conformance-infra namespace should fail to attach to a Listener that does not allow the HTTPRoute kind", + Manifests: []string{"tests/httproute-disallowed-kind.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { - routeName := types.NamespacedName{Name: "invalid-cross-namespace", Namespace: "gateway-conformance-web-backend"} - gwName := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} + // This test creates an additional Gateway in the gateway-conformance-infra + // namespace so we have to wait for it to be ready. + kubernetes.NamespacesMustBeReady(t, suite.Client, []string{"gateway-conformance-infra"}, 300) + + routeName := types.NamespacedName{Name: "disallowed-kind", Namespace: "gateway-conformance-infra"} + gwName := types.NamespacedName{Name: "tlsroutes-only", Namespace: "gateway-conformance-infra"} - // TODO: Determine if this is actually what we want. It is likely - // preferable to have status set with some kind of warning/error message - // but that is also unlikely to be universally achievable. t.Run("Route should not have Parents set in status", func(t *testing.T) { - parents := []v1alpha2.RouteParentStatus{} - kubernetes.HTTPRouteMustHaveParents(t, suite.Client, routeName, parents, true, 60) + kubernetes.HTTPRouteMustHaveNoAcceptedParents(t, suite.Client, routeName, 60) }) t.Run("Gateway should have 0 Routes attached", func(t *testing.T) { diff --git a/conformance/tests/httproute-disallowed-kind.yaml b/conformance/tests/httproute-disallowed-kind.yaml new file mode 100644 index 0000000000..61639cf4fe --- /dev/null +++ b/conformance/tests/httproute-disallowed-kind.yaml @@ -0,0 +1,32 @@ +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: Gateway +metadata: + name: tlsroutes-only + namespace: gateway-conformance-infra +spec: + gatewayClassName: {GATEWAY_CLASS_NAME} + listeners: + - name: tls + port: 443 + protocol: TLS + tls: + mode: Passthrough + allowedRoutes: + namespaces: + from: Same + kinds: + - kind: TLSRoute +--- +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: disallowed-kind + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: tlsroutes-only + namespace: gateway-conformance-infra + rules: + - backendRefs: + - name: infra-backend-v1 + port: 8080 diff --git a/conformance/tests/httproute-exact-path-matching.go b/conformance/tests/httproute-exact-path-matching.go new file mode 100644 index 0000000000..876f5ffd9b --- /dev/null +++ b/conformance/tests/httproute-exact-path-matching.go @@ -0,0 +1,74 @@ +/* +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 tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, HTTPExactPathMatching) +} + +var HTTPExactPathMatching = suite.ConformanceTest{ + ShortName: "HTTPExactPathMatching", + Description: "A single HTTPRoute with exact path matching for different backends", + Manifests: []string{"tests/httproute-exact-path-matching.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "exact-matching", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeReady(t, suite.Client, suite.ControllerName, gwNN, routeNN) + + testCases := []http.ExpectedResponse{ + { + Request: http.ExpectedRequest{Path: "/one"}, + Backend: "infra-backend-v1", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Path: "/two"}, + Backend: "infra-backend-v2", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Path: "/"}, + StatusCode: 404, + }, { + Request: http.ExpectedRequest{Path: "/one/example"}, + StatusCode: 404, + }, { + Request: http.ExpectedRequest{Path: "/two/"}, + StatusCode: 404, + }, + } + + for i := range testCases { + // Declare tc here to avoid loop variable + // reuse issues across parallel tests. + tc := testCases[i] + t.Run(testName(tc, i), func(t *testing.T) { + t.Parallel() + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, gwAddr, tc) + }) + } + }, +} diff --git a/conformance/tests/httproute-exact-path-matching.yaml b/conformance/tests/httproute-exact-path-matching.yaml new file mode 100644 index 0000000000..b6326871b4 --- /dev/null +++ b/conformance/tests/httproute-exact-path-matching.yaml @@ -0,0 +1,23 @@ +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: exact-matching + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: Exact + value: /one + backendRefs: + - name: infra-backend-v1 + port: 8080 + - matches: + - path: + type: Exact + value: /two + backendRefs: + - name: infra-backend-v2 + port: 8080 diff --git a/conformance/tests/httproute-header-matching.go b/conformance/tests/httproute-header-matching.go new file mode 100644 index 0000000000..dfeb2b4c59 --- /dev/null +++ b/conformance/tests/httproute-header-matching.go @@ -0,0 +1,92 @@ +/* +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 tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, HTTPRouteHeaderMatching) +} + +var HTTPRouteHeaderMatching = suite.ConformanceTest{ + ShortName: "HTTPRouteHeaderMatching", + Description: "A single HTTPRoute with header matching for different backends", + Manifests: []string{"tests/httproute-header-matching.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "header-matching", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeReady(t, suite.Client, suite.ControllerName, gwNN, routeNN) + + testCases := []http.ExpectedResponse{{ + Request: http.ExpectedRequest{Path: "/", Headers: map[string]string{"Version": "one"}}, + Backend: "infra-backend-v1", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Path: "/", Headers: map[string]string{"Version": "two"}}, + Backend: "infra-backend-v2", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Path: "/", Headers: map[string]string{"Version": "two", "Color": "orange"}}, + Backend: "infra-backend-v1", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Path: "/", Headers: map[string]string{"Color": "orange"}}, + StatusCode: 404, + }, { + Request: http.ExpectedRequest{Path: "/", Headers: map[string]string{"Some-Other-Header": "one"}}, + StatusCode: 404, + }, { + Request: http.ExpectedRequest{Path: "/", Headers: map[string]string{"Color": "blue"}}, + Backend: "infra-backend-v1", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Path: "/", Headers: map[string]string{"Color": "green"}}, + Backend: "infra-backend-v1", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Path: "/", Headers: map[string]string{"Color": "red"}}, + Backend: "infra-backend-v2", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Path: "/", Headers: map[string]string{"Color": "yellow"}}, + Backend: "infra-backend-v2", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Path: "/", Headers: map[string]string{"Color": "purple"}}, + StatusCode: 404, + }} + + for i := range testCases { + // Declare tc here to avoid loop variable + // reuse issues across parallel tests. + tc := testCases[i] + t.Run(testName(tc, i), func(t *testing.T) { + t.Parallel() + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, gwAddr, tc) + }) + } + }, +} diff --git a/conformance/tests/httproute-header-matching.yaml b/conformance/tests/httproute-header-matching.yaml new file mode 100644 index 0000000000..b9009615bf --- /dev/null +++ b/conformance/tests/httproute-header-matching.yaml @@ -0,0 +1,57 @@ +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: header-matching + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + # Matches "version: one" + - matches: + - headers: + - name: version + value: one + backendRefs: + - name: infra-backend-v1 + port: 8080 + # Matches "version: two" + - matches: + - headers: + - name: version + value: two + backendRefs: + - name: infra-backend-v2 + port: 8080 + # Matches "version: two" AND "color: orange" + - matches: + - headers: + - name: version + value: two + - name: color + value: orange + backendRefs: + - name: infra-backend-v1 + port: 8080 + # Matches "color: blue" OR "color: green" + - matches: + - headers: + - name: color + value: blue + - headers: + - name: color + value: green + backendRefs: + - name: infra-backend-v1 + port: 8080 + # Matches "color: red" OR "color: yellow" + - matches: + - headers: + - name: color + value: red + - headers: + - name: color + value: yellow + backendRefs: + - name: infra-backend-v2 + port: 8080 diff --git a/conformance/tests/httproute-invalid-cross-namespace-backend-ref.go b/conformance/tests/httproute-invalid-cross-namespace-backend-ref.go new file mode 100644 index 0000000000..37ab26f668 --- /dev/null +++ b/conformance/tests/httproute-invalid-cross-namespace-backend-ref.go @@ -0,0 +1,75 @@ +/* +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 tests + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, HTTPRouteInvalidCrossNamespaceBackendRef) +} + +var HTTPRouteInvalidCrossNamespaceBackendRef = suite.ConformanceTest{ + ShortName: "HTTPRouteInvalidCrossNamespaceBackendRef", + Description: "A single HTTPRoute in the gateway-conformance-infra namespace should set a ResolvedRefs status False with reason RefNotPermitted when attempting to bind to a Gateway in the same namespace if the route has a BackendRef Service in the gateway-conformance-web-backend namespace and a ReferenceGrant granting permission to route to that Service does not exist", + Exemptions: []suite.ExemptFeature{ + suite.ExemptReferenceGrant, + }, + Manifests: []string{"tests/httproute-invalid-cross-namespace-backend-ref.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + routeNN := types.NamespacedName{Name: "invalid-cross-namespace-backend-ref", Namespace: "gateway-conformance-infra"} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} + + ns := v1alpha2.Namespace(gwNN.Namespace) + kind := v1alpha2.Kind("Gateway") + + // TODO(mikemorris): Add check for Accepted condition once + // https://github.com/kubernetes-sigs/gateway-api/issues/1112 + // has been resolved + t.Run("Route status should have a route parent status with a ResolvedRefs condition with status False and reason RefNotPermitted", func(t *testing.T) { + parents := []v1alpha2.RouteParentStatus{{ + ParentRef: v1alpha2.ParentReference{ + Group: (*v1alpha2.Group)(&v1alpha2.GroupVersion.Group), + Kind: &kind, + Name: v1alpha2.ObjectName(gwNN.Name), + Namespace: &ns, + }, + ControllerName: v1alpha2.GatewayController(suite.ControllerName), + Conditions: []metav1.Condition{{ + Type: string(v1alpha2.RouteConditionResolvedRefs), + Status: metav1.ConditionFalse, + Reason: string(v1alpha2.RouteReasonRefNotPermitted), + }}, + }} + + kubernetes.HTTPRouteMustHaveParents(t, suite.Client, routeNN, parents, false, 60) + }) + + // TODO(mikemorris): Add check for Listener attached routes or + // Listener ResolvedRefs RefNotPermitted condition once + // https://github.com/kubernetes-sigs/gateway-api/issues/1112 + // has been resolved + }, +} diff --git a/conformance/tests/httproute-invalid-cross-namespace-backend-ref.yaml b/conformance/tests/httproute-invalid-cross-namespace-backend-ref.yaml new file mode 100644 index 0000000000..6503d57ee8 --- /dev/null +++ b/conformance/tests/httproute-invalid-cross-namespace-backend-ref.yaml @@ -0,0 +1,13 @@ +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: invalid-cross-namespace-backend-ref + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - backendRefs: + - name: web-backend + namespace: gateway-conformance-web-backend + port: 8080 diff --git a/conformance/tests/httproute-invalid-cross-namespace-parent-ref.go b/conformance/tests/httproute-invalid-cross-namespace-parent-ref.go new file mode 100644 index 0000000000..79906b9e43 --- /dev/null +++ b/conformance/tests/httproute-invalid-cross-namespace-parent-ref.go @@ -0,0 +1,70 @@ +/* +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 tests + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, HTTPRouteInvalidCrossNamespaceParentRef) +} + +var HTTPRouteInvalidCrossNamespaceParentRef = suite.ConformanceTest{ + ShortName: "HTTPRouteInvalidCrossNamespaceParentRef", + Description: "A single HTTPRoute in the gateway-conformance-web-backend namespace should fail to attach to a Gateway in another namespace that it is not allowed to", + Manifests: []string{"tests/httproute-invalid-cross-namespace-parent-ref.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + routeName := types.NamespacedName{Name: "invalid-cross-namespace-parent-ref", Namespace: "gateway-conformance-web-backend"} + gwName := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} + + t.Run("Route should not have Parents set in status", func(t *testing.T) { + kubernetes.HTTPRouteMustHaveNoAcceptedParents(t, suite.Client, routeName, 60) + }) + + t.Run("Gateway should have 0 Routes attached", func(t *testing.T) { + require.Eventually(t, func() bool { + gw := &v1alpha2.Gateway{} + if err := suite.Client.Get(context.TODO(), gwName, gw); err != nil { + t.Logf("error fetching gateway: %v", err) + return false + } + + // There are two valid ways to represent this: + // 1. No listeners in status + // 2. One listener in status with 0 attached routes + if len(gw.Status.Listeners) == 0 { + // No listeners in status. + return true + } else if len(gw.Status.Listeners) == 1 { + // Listener with no attached routes + return gw.Status.Listeners[0].AttachedRoutes == 0 + } + return false + }, time.Second*15, time.Second, "Expected no attached routes") + }) + }, +} diff --git a/conformance/tests/httproute-invalid-cross-namespace.yaml b/conformance/tests/httproute-invalid-cross-namespace-parent-ref.yaml similarity index 84% rename from conformance/tests/httproute-invalid-cross-namespace.yaml rename to conformance/tests/httproute-invalid-cross-namespace-parent-ref.yaml index 2031c887bd..9239422836 100644 --- a/conformance/tests/httproute-invalid-cross-namespace.yaml +++ b/conformance/tests/httproute-invalid-cross-namespace-parent-ref.yaml @@ -1,7 +1,7 @@ apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: - name: invalid-cross-namespace + name: invalid-cross-namespace-parent-ref namespace: gateway-conformance-web-backend spec: parentRefs: diff --git a/conformance/tests/httproute-invalid-reference-policy.go b/conformance/tests/httproute-invalid-reference-policy.go new file mode 100644 index 0000000000..79081411f6 --- /dev/null +++ b/conformance/tests/httproute-invalid-reference-policy.go @@ -0,0 +1,111 @@ +/* +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 tests + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, HTTPRouteInvalidReferenceGrant) +} + +var HTTPRouteInvalidReferenceGrant = suite.ConformanceTest{ + ShortName: "HTTPRouteInvalidReferenceGrant", + Description: "A single HTTPRoute in the gateway-conformance-infra namespace should fail to attach to a Gateway in the same namespace if the route has a backendRef Service in the gateway-conformance-app-backend namespace and a ReferenceGrant exists but does not grant permission to route to that specific Service", + Features: []suite.SupportedFeature{ + suite.SupportReferenceGrant, + }, + Manifests: []string{"tests/httproute-invalid-reference-grant.yaml"}, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + routeNN := types.NamespacedName{Name: "invalid-reference-grant", Namespace: "gateway-conformance-infra"} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} + + ns := v1alpha2.Namespace(gwNN.Namespace) + gwKind := v1alpha2.Kind("Gateway") + + t.Run("Route status should have a route parent status with a ResolvedRefs condition with status False and reason RefNotPermitted", func(t *testing.T) { + parents := []v1alpha2.RouteParentStatus{{ + ParentRef: v1alpha2.ParentReference{ + Group: (*v1alpha2.Group)(&v1alpha2.GroupVersion.Group), + Kind: &gwKind, + Name: v1alpha2.ObjectName(gwNN.Name), + Namespace: &ns, + }, + ControllerName: v1alpha2.GatewayController(s.ControllerName), + Conditions: []metav1.Condition{{ + Type: string(v1alpha2.RouteConditionResolvedRefs), + Status: metav1.ConditionFalse, + Reason: string(v1alpha2.RouteReasonRefNotPermitted), + }}, + }} + + kubernetes.HTTPRouteMustHaveParents(t, s.Client, routeNN, parents, false, 60) + }) + + // TODO(mikemorris): Un-comment check for Listener ResolvedRefs + // RefNotPermitted condition and/or add check for attached + // routes and any expected Listener conditions once + // https://github.com/kubernetes-sigs/gateway-api/issues/1112 + // has been resolved + // t.Run("Gateway listener should have a ResolvedRefs condition with status False and reason RefNotPermitted", func(t *testing.T) { + // listeners := []v1alpha2.ListenerStatus{{ + // Name: v1alpha2.SectionName("http"), + // SupportedKinds: []v1alpha2.RouteGroupKind{{ + // Group: (*v1alpha2.Group)(&v1alpha2.GroupVersion.Group), + // Kind: v1alpha2.Kind("HTTPRoute"), + // }}, + // Conditions: []metav1.Condition{{ + // Type: string(v1alpha2.RouteConditionResolvedRefs), + // Status: metav1.ConditionFalse, + // Reason: string(v1alpha2.RouteReasonRefNotPermitted), + // }}, + // }} + + // kubernetes.GatewayStatusMustHaveListeners(t, s.Client, gwNN, listeners, 60) + // }) + + // TODO(mikemorris): Add routeNN to the end of the arguments below + // to add check for Accepted condition once + // https://github.com/kubernetes-sigs/gateway-api/issues/1112 + // has been resolved + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeReady(t, s.Client, s.ControllerName, gwNN) + + // TODO(mikemorris): Add check for HTTP requests successfully reaching + // app-backend-v1 at path "/" if it is determined that a Route with at + // at least one allowed BackendRef should be accepted by a Gateway + // and partially configured. + + t.Run("Simple HTTP request should not reach app-backend-v2", func(t *testing.T) { + http.MakeRequestAndExpectEventuallyConsistentResponse(t, s.RoundTripper, gwAddr, http.ExpectedResponse{ + Request: http.ExpectedRequest{ + Method: "GET", + Path: "/v2", + }, + StatusCode: 404, + }) + }) + }, +} diff --git a/conformance/tests/httproute-invalid-reference-policy.yaml b/conformance/tests/httproute-invalid-reference-policy.yaml new file mode 100644 index 0000000000..144109a288 --- /dev/null +++ b/conformance/tests/httproute-invalid-reference-policy.yaml @@ -0,0 +1,36 @@ +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: ReferenceGrant +metadata: + name: invalid-reference-grant + namespace: gateway-conformance-app-backend +spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: gateway-conformance-infra + to: + - group: "" + kind: Service + name: app-backend-v1 +--- +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: invalid-reference-grant + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: "/v2" + backendRefs: + - name: app-backend-v2 + namespace: gateway-conformance-app-backend + port: 8080 + - backendRefs: + - name: app-backend-v1 + namespace: gateway-conformance-app-backend + port: 8080 diff --git a/conformance/tests/httproute-listener-hostname-matching.go b/conformance/tests/httproute-listener-hostname-matching.go new file mode 100644 index 0000000000..9fa4b6a5cc --- /dev/null +++ b/conformance/tests/httproute-listener-hostname-matching.go @@ -0,0 +1,94 @@ +/* +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 tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, HTTPRouteListenerHostnameMatching) +} + +var HTTPRouteListenerHostnameMatching = suite.ConformanceTest{ + ShortName: "HTTPRouteListenerHostnameMatching", + Description: "Multiple HTTP listeners with the same port and different hostnames, each with a different HTTPRoute", + Manifests: []string{"tests/httproute-listener-hostname-matching.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + + // This test creates an additional Gateway in the gateway-conformance-infra + // namespace so we have to wait for it to be ready. + kubernetes.NamespacesMustBeReady(t, suite.Client, []string{ns}, 300) + + gwNN := types.NamespacedName{Name: "httproute-listener-hostname-matching", Namespace: ns} + routes := []types.NamespacedName{ + {Namespace: ns, Name: "backend-v1"}, + {Namespace: ns, Name: "backend-v2"}, + {Namespace: ns, Name: "backend-v3"}, + } + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeReady(t, suite.Client, suite.ControllerName, gwNN, routes...) + + testCases := []http.ExpectedResponse{{ + Request: http.ExpectedRequest{Host: "bar.com", Path: "/"}, + Backend: "infra-backend-v1", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Host: "foo.bar.com", Path: "/"}, + Backend: "infra-backend-v2", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Host: "baz.bar.com", Path: "/"}, + Backend: "infra-backend-v3", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Host: "boo.bar.com", Path: "/"}, + Backend: "infra-backend-v3", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Host: "multiple.prefixes.bar.com", Path: "/"}, + Backend: "infra-backend-v3", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Host: "multiple.prefixes.foo.com", Path: "/"}, + Backend: "infra-backend-v3", + Namespace: ns, + }, { + Request: http.ExpectedRequest{Host: "foo.com", Path: "/"}, + StatusCode: 404, + }, { + Request: http.ExpectedRequest{Host: "no.matching.host", Path: "/"}, + StatusCode: 404, + }} + + for i := range testCases { + // Declare tc here to avoid loop variable + // reuse issues across parallel tests. + tc := testCases[i] + t.Run(testName(tc, i), func(t *testing.T) { + t.Parallel() + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, gwAddr, tc) + }) + } + }, +} diff --git a/conformance/tests/httproute-listener-hostname-matching.yaml b/conformance/tests/httproute-listener-hostname-matching.yaml new file mode 100644 index 0000000000..84ab7586d6 --- /dev/null +++ b/conformance/tests/httproute-listener-hostname-matching.yaml @@ -0,0 +1,84 @@ +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: Gateway +metadata: + name: httproute-listener-hostname-matching + namespace: gateway-conformance-infra +spec: + gatewayClassName: {GATEWAY_CLASS_NAME} + listeners: + - name: listener-1 + port: 80 + protocol: HTTP + allowedRoutes: + namespaces: + from: Same + hostname: bar.com + - name: listener-2 + port: 80 + protocol: HTTP + allowedRoutes: + namespaces: + from: Same + hostname: foo.bar.com + - name: listener-3 + port: 80 + protocol: HTTP + allowedRoutes: + namespaces: + from: Same + hostname: "*.bar.com" + - name: listener-4 + port: 80 + protocol: HTTP + allowedRoutes: + namespaces: + from: Same + hostname: "*.foo.com" +--- +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: backend-v1 + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: httproute-listener-hostname-matching + namespace: gateway-conformance-infra + sectionName: listener-1 + rules: + - backendRefs: + - name: infra-backend-v1 + port: 8080 +--- +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: backend-v2 + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: httproute-listener-hostname-matching + namespace: gateway-conformance-infra + sectionName: listener-2 + rules: + - backendRefs: + - name: infra-backend-v2 + port: 8080 +--- +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: backend-v3 + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: httproute-listener-hostname-matching + namespace: gateway-conformance-infra + sectionName: listener-3 + - name: httproute-listener-hostname-matching + namespace: gateway-conformance-infra + sectionName: listener-4 + rules: + - backendRefs: + - name: infra-backend-v3 + port: 8080 diff --git a/conformance/tests/httproute-matching-across-routes.go b/conformance/tests/httproute-matching-across-routes.go index bd7b259ffe..8989390515 100644 --- a/conformance/tests/httproute-matching-across-routes.go +++ b/conformance/tests/httproute-matching-across-routes.go @@ -109,7 +109,7 @@ var HTTPRouteMatchingAcrossRoutes = suite.ConformanceTest{ tc := testCases[i] t.Run(testName(tc, i), func(t *testing.T) { t.Parallel() - http.MakeRequestAndExpectResponse(t, suite.RoundTripper, gwAddr, tc) + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, gwAddr, tc) }) } }, diff --git a/conformance/tests/httproute-matching.go b/conformance/tests/httproute-matching.go index 7fc404fc8e..3ec318f10d 100644 --- a/conformance/tests/httproute-matching.go +++ b/conformance/tests/httproute-matching.go @@ -72,7 +72,7 @@ var HTTPRouteMatching = suite.ConformanceTest{ tc := testCases[i] t.Run(testName(tc, i), func(t *testing.T) { t.Parallel() - http.MakeRequestAndExpectResponse(t, suite.RoundTripper, gwAddr, tc) + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, gwAddr, tc) }) } }, diff --git a/conformance/tests/httproute-reference-policy.go b/conformance/tests/httproute-reference-policy.go new file mode 100644 index 0000000000..50f720c6c7 --- /dev/null +++ b/conformance/tests/httproute-reference-policy.go @@ -0,0 +1,57 @@ +/* +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 tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, HTTPRouteReferenceGrant) +} + +var HTTPRouteReferenceGrant = suite.ConformanceTest{ + ShortName: "HTTPRouteReferenceGrant", + Description: "A single HTTPRoute in the gateway-conformance-infra namespace, with a backendRef in the gateway-conformance-web-backend namespace, should attach to Gateway in the gateway-conformance-infra namespace", + Features: []suite.SupportedFeature{ + suite.SupportReferenceGrant, + }, + Manifests: []string{"tests/httproute-reference-grant.yaml"}, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + routeNN := types.NamespacedName{Name: "reference-grant", Namespace: "gateway-conformance-infra"} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeReady(t, s.Client, s.ControllerName, gwNN, routeNN) + + t.Run("Simple HTTP request should reach web-backend", func(t *testing.T) { + http.MakeRequestAndExpectEventuallyConsistentResponse(t, s.RoundTripper, gwAddr, http.ExpectedResponse{ + Request: http.ExpectedRequest{ + Method: "GET", + Path: "/", + }, + StatusCode: 200, + Backend: "web-backend", + Namespace: "gateway-conformance-web-backend", + }) + }) + }, +} diff --git a/conformance/tests/httproute-reference-policy.yaml b/conformance/tests/httproute-reference-policy.yaml new file mode 100644 index 0000000000..6dbbd273c4 --- /dev/null +++ b/conformance/tests/httproute-reference-policy.yaml @@ -0,0 +1,28 @@ +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: ReferenceGrant +metadata: + name: reference-grant + namespace: gateway-conformance-web-backend +spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: gateway-conformance-infra + to: + - group: "" + kind: Service + name: web-backend +--- +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: reference-grant + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - backendRefs: + - name: web-backend + namespace: gateway-conformance-web-backend + port: 8080 diff --git a/conformance/tests/httproute-simple-same-namespace.go b/conformance/tests/httproute-simple-same-namespace.go index 3cf702f42c..3cc971237f 100644 --- a/conformance/tests/httproute-simple-same-namespace.go +++ b/conformance/tests/httproute-simple-same-namespace.go @@ -17,16 +17,13 @@ limitations under the License. package tests import ( - "net/url" "testing" - "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/gateway-api/apis/v1alpha2" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" - "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" "sigs.k8s.io/gateway-api/conformance/utils/suite" ) @@ -45,19 +42,8 @@ var HTTPRouteSimpleSameNamespace = suite.ConformanceTest{ gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeReady(t, suite.Client, suite.ControllerName, gwNN, routeNN) t.Run("Simple HTTP request should reach infra-backend", func(t *testing.T) { - t.Logf("Making request to http://%s", gwAddr) - cReq, cRes, err := suite.RoundTripper.CaptureRoundTrip(roundtripper.Request{ - URL: url.URL{Scheme: "http", Host: gwAddr}, - Protocol: "HTTP", - }) - - require.NoErrorf(t, err, "error making request") - - http.ExpectResponse(t, cReq, cRes, http.ExpectedResponse{ - Request: http.ExpectedRequest{ - Method: "GET", - Path: "/", - }, + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, gwAddr, http.ExpectedResponse{ + Request: http.ExpectedRequest{Path: "/"}, StatusCode: 200, Backend: "infra-backend-v1", Namespace: "gateway-conformance-infra", diff --git a/conformance/utils/flags/flags.go b/conformance/utils/flags/flags.go new file mode 100644 index 0000000000..db2795e2cc --- /dev/null +++ b/conformance/utils/flags/flags.go @@ -0,0 +1,30 @@ +/* +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. +*/ + +// flags contains command-line flag definitions for the conformance +// tests. They're in this package so they can be shared among the +// various suites that are all run by the same Makefile invocation. +package flags + +import ( + "flag" +) + +var ( + GatewayClassName = flag.String("gateway-class", "gateway-conformance", "Name of GatewayClass to use for tests") + ShowDebug = flag.Bool("debug", false, "Whether to print debug logs") + CleanupBaseResources = flag.Bool("cleanup-base-resources", true, "Whether to cleanup base test resources after the run") +) diff --git a/conformance/utils/http/http.go b/conformance/utils/http/http.go index d6173d0b15..28a5b75bdc 100644 --- a/conformance/utils/http/http.go +++ b/conformance/utils/http/http.go @@ -20,9 +20,9 @@ import ( "net/url" "strings" "testing" + "time" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" ) @@ -44,9 +44,22 @@ type ExpectedRequest struct { Headers map[string]string } -// MakeRequestAndExpectResponse makes a request with the given parameters and -// verifies the response matches the provided ExpectedResponse. -func MakeRequestAndExpectResponse(t *testing.T, r roundtripper.RoundTripper, gwAddr string, expected ExpectedResponse) { +// maxTimeToConsistency is the maximum time that WaitForConsistency will wait for +// requiredConsecutiveSuccesses requests to succeed in a row before failing the test. +const maxTimeToConsistency = 30 * time.Second + +// requiredConsecutiveSuccesses is the number of requests that must succeed in a row +// for MakeRequestAndExpectEventuallyConsistentResponse to consider the response "consistent" +// before making additional assertions on the response body. If this number is not reached within +// maxTimeToConsistency, the test will fail. +const requiredConsecutiveSuccesses = 3 + +// MakeRequestAndExpectEventuallyConsistentResponse makes a request with the given parameters, +// understanding that the request may fail for some amount of time. +// +// Once the request succeeds consistently with the response having the expected status code, make +// additional assertions on the response body using the provided ExpectedResponse. +func MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, r roundtripper.RoundTripper, gwAddr string, expected ExpectedResponse) { t.Helper() if expected.Request.Method == "" { @@ -72,12 +85,76 @@ func MakeRequestAndExpectResponse(t *testing.T, r roundtripper.RoundTripper, gwA req.Headers[name] = []string{value} } } - cReq, cRes, err := r.CaptureRoundTrip(req) - require.NoErrorf(t, err, "error making request") + cReq, cRes := WaitForConsistency(t, r, req, expected, requiredConsecutiveSuccesses) ExpectResponse(t, cReq, cRes, expected) } +// awaitConvergence runs the given function until it returns 'true' `threshold` times in a row. +// Each failed attempt has a 1s delay; successful attempts have no delay. +func awaitConvergence(t *testing.T, threshold int, fn func() bool) { + successes := 0 + attempts := 0 + to := time.After(maxTimeToConsistency) + delay := time.Second + for { + select { + case <-to: + t.Fatalf("timeout while waiting after %d attempts", attempts) + default: + } + + completed := fn() + attempts++ + if completed { + successes++ + if successes >= threshold { + return + } + // Skip delay if we have a success + continue + } + + successes = 0 + select { + // Capture the overall timeout + case <-to: + t.Fatalf("timeout while waiting after %d attempts, %d/%d sucessess", attempts, successes, threshold) + // And the per-try delay + case <-time.After(delay): + } + } +} + +// WaitForConsistency repeats the provided request until it completes with a response having +// the expected status code consistently. The provided threshold determines how many times in +// a row this must occur to be considered "consistent". +func WaitForConsistency(t *testing.T, r roundtripper.RoundTripper, req roundtripper.Request, expected ExpectedResponse, threshold int) (*roundtripper.CapturedRequest, *roundtripper.CapturedResponse) { + var ( + cReq *roundtripper.CapturedRequest + cRes *roundtripper.CapturedResponse + err error + ) + + awaitConvergence(t, threshold, func() bool { + cReq, cRes, err = r.CaptureRoundTrip(req) + if err != nil { + t.Logf("Request failed, not ready yet: %v", err.Error()) + return false + } + + if cRes.StatusCode != expected.StatusCode { + t.Logf("Expected response to have status %d but got %d, not ready yet", expected.StatusCode, cRes.StatusCode) + return false + } + + return true + }) + t.Logf("Request passed") + + return cReq, cRes +} + // ExpectResponse verifies that a captured request and response match the // provided ExpectedResponse. func ExpectResponse(t *testing.T, cReq *roundtripper.CapturedRequest, cRes *roundtripper.CapturedResponse, expected ExpectedResponse) { diff --git a/conformance/utils/kubernetes/apply.go b/conformance/utils/kubernetes/apply.go index f6a6743368..a4917b85b1 100644 --- a/conformance/utils/kubernetes/apply.go +++ b/conformance/utils/kubernetes/apply.go @@ -34,35 +34,127 @@ import ( "k8s.io/apimachinery/pkg/util/yaml" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/gateway-api/apis/v1alpha2" "sigs.k8s.io/gateway-api/conformance" ) -// MustApplyWithCleanup creates or updates Kubernetes resources defined with the -// provided YAML file and registers a cleanup function for resources it created. -// Note that this does not remove resources that already existed in the cluster. -func MustApplyWithCleanup(t *testing.T, c client.Client, location string, gcName string, cleanup bool) { - data, err := getContentsFromPathOrURL(location) - require.NoError(t, err) +// Applier prepares manifests depending on the available options and applies +// them to the Kubernetes cluster. +type Applier struct { + NamespaceLabels map[string]string + // ValidUniqueListenerPorts maps each listener port of each Gateway in the + // manifests to a valid, unique port. There must be as many + // ValidUniqueListenerPorts as there are listeners in the set of manifests. + // For example, given two Gateways, each with 2 listeners, there should be + // four ValidUniqueListenerPorts. + // If empty or nil, ports are not modified. + ValidUniqueListenerPorts []v1alpha2.PortNumber +} + +// prepareGateway adjusts both listener ports and the gatewayClassName. It +// returns an index pointing to the next valid listener port. +func prepareGateway(t *testing.T, uObj *unstructured.Unstructured, gatewayClassName string, validListenerPorts []v1alpha2.PortNumber, portIndex int) int { + err := unstructured.SetNestedField(uObj.Object, gatewayClassName, "spec", "gatewayClassName") + require.NoErrorf(t, err, "error setting `spec.gatewayClassName` on %s Gateway resource", uObj.GetName()) + + if len(validListenerPorts) > 0 { + listeners, _, err := unstructured.NestedSlice(uObj.Object, "spec", "listeners") + require.NoErrorf(t, err, "error getting `spec.listeners` on %s Gateway resource", uObj.GetName()) + + for i, uListener := range listeners { + require.Less(t, portIndex, len(validListenerPorts), "not enough unassigned valid ports for `spec.listeners[%d]` on %s Gateway resource", i, uObj.GetName()) + + listener, ok := uListener.(map[string]interface{}) + require.Truef(t, ok, "unexpected type at `spec.listeners[%d]` on %s Gateway resource", i, uObj.GetName()) + + nextPort := validListenerPorts[portIndex] + err = unstructured.SetNestedField(listener, int64(nextPort), "port") + require.NoErrorf(t, err, "error setting `spec.listeners[%d].port` on %s Gateway resource", i, uObj.GetName()) + + portIndex++ + listeners[i] = listener + } + + err = unstructured.SetNestedSlice(uObj.Object, listeners, "spec", "listeners") + require.NoErrorf(t, err, "error setting `spec.listeners` on %s Gateway resource", uObj.GetName()) + } + + return portIndex +} + +// prepareNamespace adjusts the Namespace labels. +func prepareNamespace(t *testing.T, uObj *unstructured.Unstructured, namespaceLabels map[string]string) { + labels, _, err := unstructured.NestedStringMap(uObj.Object, "metadata", "labels") + require.NoErrorf(t, err, "error getting labels on Namespace %s", uObj.GetName()) + + for k, v := range namespaceLabels { + if labels == nil { + labels = map[string]string{} + } + + labels[k] = v + } + + // SetNestedStringMap converts nil to an empty map + if labels != nil { + err = unstructured.SetNestedStringMap(uObj.Object, labels, "metadata", "labels") + } + require.NoErrorf(t, err, "error setting labels on Namespace %s", uObj.GetName()) +} + +// prepareResources uses the options from an Applier to tweak resources given by +// a set of manifests. +func (a Applier) prepareResources(t *testing.T, decoder *yaml.YAMLOrJSONDecoder, gcName string) ([]unstructured.Unstructured, error) { + var resources []unstructured.Unstructured + + // portIndex is incremented for each listener we see. For a manifest file + // with 2 gateways, each with 2 listeners, it will be incremented 4 times. + portIndex := 0 - decoder := yaml.NewYAMLOrJSONDecoder(data, 4096) for { uObj := unstructured.Unstructured{} - if decodeErr := decoder.Decode(&uObj); decodeErr != nil { - if errors.Is(decodeErr, io.EOF) { + if err := decoder.Decode(&uObj); err != nil { + if errors.Is(err, io.EOF) { break } - t.Logf("manifest: %s", data.String()) - require.NoErrorf(t, decodeErr, "error parsing manifest") + return nil, err } if len(uObj.Object) == 0 { continue } if uObj.GetKind() == "Gateway" { - err = unstructured.SetNestedField(uObj.Object, gcName, "spec", "gatewayClassName") - require.NoErrorf(t, err, "error setting `spec.gatewayClassName` on %s Gateway resource", uObj.GetName()) + portIndex = prepareGateway(t, &uObj, gcName, a.ValidUniqueListenerPorts, portIndex) + } + + if uObj.GetKind() == "Namespace" && uObj.GetObjectKind().GroupVersionKind().Group == "" { + prepareNamespace(t, &uObj, a.NamespaceLabels) } + resources = append(resources, uObj) + } + + return resources, nil +} + +// MustApplyWithCleanup creates or updates Kubernetes resources defined with the +// provided YAML file and registers a cleanup function for resources it created. +// Note that this does not remove resources that already existed in the cluster. +func (a Applier) MustApplyWithCleanup(t *testing.T, c client.Client, location string, gcName string, cleanup bool) { + data, err := getContentsFromPathOrURL(location) + require.NoError(t, err) + + decoder := yaml.NewYAMLOrJSONDecoder(data, 4096) + + resources, err := a.prepareResources(t, decoder, gcName) + if err != nil { + t.Logf("manifest: %s", data.String()) + require.NoErrorf(t, err, "error parsing manifest") + } + + for i := range resources { + uObj := &resources[i] + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -74,14 +166,15 @@ func MustApplyWithCleanup(t *testing.T, c client.Client, location string, gcName require.NoErrorf(t, err, "error getting resource") } t.Logf("Creating %s %s", uObj.GetName(), uObj.GetKind()) - err = c.Create(ctx, &uObj) + err = c.Create(ctx, uObj) require.NoErrorf(t, err, "error creating resource") if cleanup { t.Cleanup(func() { ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - err = c.Delete(ctx, &uObj) + t.Logf("Deleting %s %s", uObj.GetName(), uObj.GetKind()) + err = c.Delete(ctx, uObj) require.NoErrorf(t, err, "error deleting resource") }) } @@ -90,13 +183,14 @@ func MustApplyWithCleanup(t *testing.T, c client.Client, location string, gcName uObj.SetResourceVersion(fetchedObj.GetResourceVersion()) t.Logf("Updating %s %s", uObj.GetName(), uObj.GetKind()) - err = c.Update(ctx, &uObj) + err = c.Update(ctx, uObj) if cleanup { t.Cleanup(func() { ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - err = c.Delete(ctx, &uObj) + t.Logf("Deleting %s %s", uObj.GetName(), uObj.GetKind()) + err = c.Delete(ctx, uObj) require.NoErrorf(t, err, "error deleting resource") }) } diff --git a/conformance/utils/kubernetes/apply_test.go b/conformance/utils/kubernetes/apply_test.go new file mode 100644 index 0000000000..6a37ae5634 --- /dev/null +++ b/conformance/utils/kubernetes/apply_test.go @@ -0,0 +1,274 @@ +/* +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 kubernetes + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/yaml" + + "sigs.k8s.io/gateway-api/apis/v1alpha2" + _ "sigs.k8s.io/gateway-api/conformance/utils/flags" +) + +func TestPrepareResources(t *testing.T) { + tests := []struct { + name string + given string + expected []unstructured.Unstructured + applier Applier + }{{ + name: "empty namespace labels", + applier: Applier{}, + given: ` +apiVersion: v1 +kind: Namespace +metadata: + name: test +`, + expected: []unstructured.Unstructured{{ + Object: map[string]interface{}{ + "apiVersion": "v1", + "kind": "Namespace", + "metadata": map[string]interface{}{ + "name": "test", + }, + }, + }}, + }, { + name: "simple namespace labels", + applier: Applier{ + NamespaceLabels: map[string]string{ + "test": "false", + }, + }, + given: ` +apiVersion: v1 +kind: Namespace +metadata: + name: test +`, + expected: []unstructured.Unstructured{{ + Object: map[string]interface{}{ + "apiVersion": "v1", + "kind": "Namespace", + "metadata": map[string]interface{}{ + "name": "test", + "labels": map[string]interface{}{ + "test": "false", + }, + }, + }, + }}, + }, { + name: "overwrite namespace labels", + applier: Applier{ + NamespaceLabels: map[string]string{ + "test": "true", + }, + }, + given: ` +apiVersion: v1 +kind: Namespace +metadata: + name: test + labels: + test: 'false' +`, + expected: []unstructured.Unstructured{{ + Object: map[string]interface{}{ + "apiVersion": "v1", + "kind": "Namespace", + "metadata": map[string]interface{}{ + "name": "test", + "labels": map[string]interface{}{ + "test": "true", + }, + }, + }, + }}, + }, { + name: "no listener ports given", + applier: Applier{}, + given: ` +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: Gateway +metadata: + name: test +spec: + gatewayClassName: {GATEWAY_CLASS_NAME} + listeners: + - name: http + port: 80 + protocol: HTTP + allowedRoutes: + namespaces: + from: Same +`, + expected: []unstructured.Unstructured{{ + Object: map[string]interface{}{ + "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "kind": "Gateway", + "metadata": map[string]interface{}{ + "name": "test", + }, + "spec": map[string]interface{}{ + "gatewayClassName": "test-class", + "listeners": []interface{}{ + map[string]interface{}{ + "name": "http", + "port": int64(80), + "protocol": "HTTP", + "allowedRoutes": map[string]interface{}{ + "namespaces": map[string]interface{}{ + "from": "Same", + }, + }, + }, + }, + }, + }, + }}, + }, { + name: "multiple gateways each with multiple listeners", + applier: Applier{ + ValidUniqueListenerPorts: []v1alpha2.PortNumber{8000, 8001, 8002, 8003}, + }, + given: ` +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: Gateway +metadata: + name: test +spec: + gatewayClassName: {GATEWAY_CLASS_NAME} + listeners: + - name: http + port: 80 + protocol: HTTP + allowedRoutes: + namespaces: + from: Same + - name: https + port: 443 + protocol: HTTPS + allowedRoutes: + namespaces: + from: Same +--- +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: Gateway +metadata: + name: test2 +spec: + gatewayClassName: {GATEWAY_CLASS_NAME} + listeners: + - name: http + port: 80 + protocol: HTTP + allowedRoutes: + namespaces: + from: Same + - name: https + port: 443 + protocol: HTTPS + allowedRoutes: + namespaces: + from: Same +`, + expected: []unstructured.Unstructured{{ + Object: map[string]interface{}{ + "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "kind": "Gateway", + "metadata": map[string]interface{}{ + "name": "test", + }, + "spec": map[string]interface{}{ + "gatewayClassName": "test-class", + "listeners": []interface{}{ + map[string]interface{}{ + "name": "http", + "port": int64(8000), + "protocol": "HTTP", + "allowedRoutes": map[string]interface{}{ + "namespaces": map[string]interface{}{ + "from": "Same", + }, + }, + }, + map[string]interface{}{ + "name": "https", + "port": int64(8001), + "protocol": "HTTPS", + "allowedRoutes": map[string]interface{}{ + "namespaces": map[string]interface{}{ + "from": "Same", + }, + }, + }, + }, + }, + }, + }, { + Object: map[string]interface{}{ + "apiVersion": "gateway.networking.k8s.io/v1alpha2", + "kind": "Gateway", + "metadata": map[string]interface{}{ + "name": "test2", + }, + "spec": map[string]interface{}{ + "gatewayClassName": "test-class", + "listeners": []interface{}{ + map[string]interface{}{ + "name": "http", + "port": int64(8002), + "protocol": "HTTP", + "allowedRoutes": map[string]interface{}{ + "namespaces": map[string]interface{}{ + "from": "Same", + }, + }, + }, + map[string]interface{}{ + "name": "https", + "port": int64(8003), + "protocol": "HTTPS", + "allowedRoutes": map[string]interface{}{ + "namespaces": map[string]interface{}{ + "from": "Same", + }, + }, + }, + }, + }, + }, + }}, + }} + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + decoder := yaml.NewYAMLOrJSONDecoder(strings.NewReader(tc.given), 4096) + + resources, err := tc.applier.prepareResources(t, decoder, "test-class") + + require.NoError(t, err, "unexpected error preparing resources") + require.EqualValues(t, tc.expected, resources) + }) + } +} diff --git a/conformance/utils/kubernetes/helpers.go b/conformance/utils/kubernetes/helpers.go index b0df4aaa4f..c4295e5aec 100644 --- a/conformance/utils/kubernetes/helpers.go +++ b/conformance/utils/kubernetes/helpers.go @@ -19,7 +19,9 @@ package kubernetes import ( "context" "fmt" + "net" "reflect" + "strconv" "strings" "testing" "time" @@ -131,7 +133,7 @@ func GatewayAndHTTPRoutesMustBeReady(t *testing.T, c client.Client, controllerNa }, ControllerName: v1alpha2.GatewayController(controllerName), Conditions: []metav1.Condition{{ - Type: string(v1alpha2.ConditionRouteAccepted), + Type: string(v1alpha2.RouteConditionAccepted), Status: metav1.ConditionTrue, }}, }} @@ -146,7 +148,7 @@ func GatewayAndHTTPRoutesMustBeReady(t *testing.T, c client.Client, controllerNa func WaitForGatewayAddress(t *testing.T, client client.Client, gwName types.NamespacedName, seconds int) (string, error) { t.Helper() - var ipAddr string + var ipAddr, port string waitFor := time.Duration(seconds) * time.Second waitErr := wait.PollImmediate(1*time.Second, waitFor, func() (bool, error) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) @@ -159,6 +161,8 @@ func WaitForGatewayAddress(t *testing.T, client client.Client, gwName types.Name return false, fmt.Errorf("error fetching Gateway: %w", err) } + port = strconv.FormatInt(int64(gw.Spec.Listeners[0].Port), 10) + // TODO: Support more than IPAddress for _, address := range gw.Status.Addresses { if address.Type != nil && *address.Type == v1alpha2.IPAddressType { @@ -170,7 +174,48 @@ func WaitForGatewayAddress(t *testing.T, client client.Client, gwName types.Name return false, nil }) require.NoErrorf(t, waitErr, "error waiting for Gateway to have at least one IP address in status") - return ipAddr, waitErr + return net.JoinHostPort(ipAddr, port), waitErr +} + +// HTTPRouteMustHaveNoAcceptedParents waits for the specified HTTPRoute to have either no parents +// or a single parent that is not accepted. This is used to validate HTTPRoute errors. +func HTTPRouteMustHaveNoAcceptedParents(t *testing.T, client client.Client, routeName types.NamespacedName, seconds int) { + t.Helper() + + var actual []v1alpha2.RouteParentStatus + waitFor := time.Duration(seconds) * time.Second + emptyChecked := false + waitErr := wait.PollImmediate(1*time.Second, waitFor, func() (bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + route := &v1alpha2.HTTPRoute{} + err := client.Get(ctx, routeName, route) + if err != nil { + return false, fmt.Errorf("error fetching HTTPRoute: %w", err) + } + + actual = route.Status.Parents + + if len(actual) == 0 { + // For empty status, we need to distinguish between "correctly did not set" and "hasn't set yet" + // Ensure we iterate at least two times (taking advantage of the 1s poll delay) to give it some time. + if !emptyChecked { + emptyChecked = true + return false, nil + } + return true, nil + } + if len(actual) > 1 { + // Only expect one parent + return false, nil + } + return conditionsMatch(t, []metav1.Condition{{ + Type: string(v1alpha2.RouteConditionAccepted), + Status: "False", + }}, actual[0].Conditions), nil + }) + require.NoErrorf(t, waitErr, "error waiting for HTTPRoute to have no accepted parents") } // HTTPRouteMustHaveParents waits for the specified HTTPRoute to have parents @@ -231,21 +276,88 @@ func parentsMatch(t *testing.T, expected, actual []v1alpha2.RouteParentStatus, n return false } } - if len(aParent.Conditions) < len(eParent.Conditions) { - t.Logf("Expected more conditions to be present") + if !conditionsMatch(t, eParent.Conditions, aParent.Conditions) { return false } - for _, condition := range eParent.Conditions { - if !findConditionInList(t, aParent.Conditions, condition.Type, string(condition.Status)) { - return false - } - } } t.Logf("Route parents matched expectations") return true } +// GatewayStatusMustHaveListeners waits for the specified Gateway to have listeners +// in status that match the expected listeners. This will cause the test to halt +// if the specified timeout is exceeded. +func GatewayStatusMustHaveListeners(t *testing.T, client client.Client, gwNN types.NamespacedName, listeners []v1alpha2.ListenerStatus, seconds int) { + t.Helper() + + var actual []v1alpha2.ListenerStatus + waitFor := time.Duration(seconds) * time.Second + waitErr := wait.PollImmediate(1*time.Second, waitFor, func() (bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + gw := &v1alpha2.Gateway{} + err := client.Get(ctx, gwNN, gw) + if err != nil { + return false, fmt.Errorf("error fetching Gateway: %w", err) + } + + actual = gw.Status.Listeners + + return listenersMatch(t, listeners, actual), nil + }) + require.NoErrorf(t, waitErr, "error waiting for Gateway status to have listeners matching expectations") +} + +// TODO(mikemorris): this and parentsMatch could possibly be rewritten as a generic function? +func listenersMatch(t *testing.T, expected, actual []v1alpha2.ListenerStatus) bool { + t.Helper() + + if len(expected) != len(actual) { + t.Logf("Expected %d Gateway status listeners, got %d", len(expected), len(actual)) + return false + } + + // TODO(mikemorris): Allow for arbitrarily ordered listeners + for i, eListener := range expected { + aListener := actual[i] + if aListener.Name != eListener.Name { + t.Logf("Name doesn't match") + return false + } + if !reflect.DeepEqual(aListener.SupportedKinds, eListener.SupportedKinds) { + t.Logf("Expected SupportedKinds to be %v, got %v", eListener.SupportedKinds, aListener.SupportedKinds) + return false + } + if aListener.AttachedRoutes != eListener.AttachedRoutes { + t.Logf("Expected AttachedRoutes to be %v, got %v", eListener.AttachedRoutes, aListener.AttachedRoutes) + return false + } + if !conditionsMatch(t, eListener.Conditions, aListener.Conditions) { + return false + } + } + + t.Logf("Gateway status listeners matched expectations") + return true +} + +func conditionsMatch(t *testing.T, expected, actual []metav1.Condition) bool { + if len(actual) < len(expected) { + t.Logf("Expected more conditions to be present") + return false + } + for _, condition := range expected { + if !findConditionInList(t, actual, condition.Type, string(condition.Status)) { + return false + } + } + + t.Logf("Conditions matched expectations") + return true +} + func findConditionInList(t *testing.T, conditions []metav1.Condition, condName, condValue string) bool { for _, cond := range conditions { if cond.Type == condName { diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index d31b6d9352..a1295c2ad5 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -19,22 +19,47 @@ package suite import ( "testing" + "golang.org/x/exp/slices" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/gateway-api/apis/v1alpha2" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" ) +// ExemptFeature allows opting out of core conformance tests at an +// individual feature granularity. +type ExemptFeature string + +const ( + // This option indicates the implementation is exempting itself from the + // requirement of a ReferenceGrant to allow cross-namesapce references, + // and has instead implemented alternative safeguards. + ExemptReferenceGrant ExemptFeature = "ReferenceGrant" +) + +// SupportedFeature allows opting in to additional conformance tests at an +// individual feature granularity. +type SupportedFeature string + +const ( + // This option indicates support for the ReferenceGrant object. + SupportReferenceGrant SupportedFeature = "ReferenceGrant" +) + // ConformanceTestSuite defines the test suite used to run Gateway API // conformance tests. type ConformanceTestSuite struct { - Client client.Client - RoundTripper roundtripper.RoundTripper - GatewayClassName string - ControllerName string - Debug bool - Cleanup bool - BaseManifests string + Client client.Client + RoundTripper roundtripper.RoundTripper + GatewayClassName string + ControllerName string + Debug bool + Cleanup bool + BaseManifests string + Applier kubernetes.Applier + ExemptFeatures []ExemptFeature + SupportedFeatures []SupportedFeature } // Options can be used to initialize a ConformanceTestSuite. @@ -42,9 +67,22 @@ type Options struct { Client client.Client GatewayClassName string Debug bool - Cleanup bool RoundTripper roundtripper.RoundTripper BaseManifests string + NamespaceLabels map[string]string + // ValidUniqueListenerPorts maps each listener port of each Gateway in the + // manifests to a valid, unique port. There must be as many + // ValidUniqueListenerPorts as there are listeners in the set of manifests. + // For example, given two Gateways, each with 2 listeners, there should be + // four ValidUniqueListenerPorts. + // If empty or nil, ports are not modified. + ValidUniqueListenerPorts []v1alpha2.PortNumber + + // CleanupBaseResources indicates whether or not the base test + // resources such as Gateways should be cleaned up after the run. + CleanupBaseResources bool + ExemptFeatures []ExemptFeature + SupportedFeatures []SupportedFeature } // New returns a new ConformanceTestSuite. @@ -59,8 +97,14 @@ func New(s Options) *ConformanceTestSuite { RoundTripper: roundTripper, GatewayClassName: s.GatewayClassName, Debug: s.Debug, - Cleanup: s.Cleanup, + Cleanup: s.CleanupBaseResources, BaseManifests: s.BaseManifests, + Applier: kubernetes.Applier{ + NamespaceLabels: s.NamespaceLabels, + ValidUniqueListenerPorts: s.ValidUniqueListenerPorts, + }, + ExemptFeatures: s.ExemptFeatures, + SupportedFeatures: s.SupportedFeatures, } // apply defaults @@ -78,7 +122,7 @@ func (suite *ConformanceTestSuite) Setup(t *testing.T) { suite.ControllerName = kubernetes.GWCMustBeAccepted(t, suite.Client, suite.GatewayClassName, 180) t.Logf("Test Setup: Applying base manifests") - kubernetes.MustApplyWithCleanup(t, suite.Client, suite.BaseManifests, suite.GatewayClassName, suite.Cleanup) + suite.Applier.MustApplyWithCleanup(t, suite.Client, suite.BaseManifests, suite.GatewayClassName, suite.Cleanup) t.Logf("Test Setup: Ensuring Gateways and Pods from base manifests are ready") namespaces := []string{ @@ -102,6 +146,8 @@ func (suite *ConformanceTestSuite) Run(t *testing.T, tests []ConformanceTest) { type ConformanceTest struct { ShortName string Description string + Exemptions []ExemptFeature + Features []SupportedFeature Manifests []string Slow bool Parallel bool @@ -114,9 +160,26 @@ func (test *ConformanceTest) Run(t *testing.T, suite *ConformanceTestSuite) { if test.Parallel { t.Parallel() } + + // Check that all features exercised by the test have been opted into by + // the suite. + for _, feature := range test.Features { + if !slices.Contains(suite.SupportedFeatures, feature) { + t.Skipf("Skipping %s: suite does not support %s", test.ShortName, feature) + } + } + + // Check that no features exercised by the test have been opted out of by + // the suite. + for _, feature := range test.Exemptions { + if !slices.Contains(suite.ExemptFeatures, feature) { + t.Skipf("Skipping %s: suite exempts %s", test.ShortName, feature) + } + } + for _, manifestLocation := range test.Manifests { t.Logf("Applying %s", manifestLocation) - kubernetes.MustApplyWithCleanup(t, suite.Client, manifestLocation, suite.GatewayClassName, true) + suite.Applier.MustApplyWithCleanup(t, suite.Client, manifestLocation, suite.GatewayClassName, true) } test.Test(t, suite) diff --git a/examples/experimental/v1alpha2/http-redirect.yaml b/examples/experimental/v1alpha2/http-redirect.yaml new file mode 100644 index 0000000000..87db55e6fc --- /dev/null +++ b/examples/experimental/v1alpha2/http-redirect.yaml @@ -0,0 +1,18 @@ +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: http-filter-1 + namespace: gateway-api-example-ns1 +spec: + parentRefs: + - name: my-filter-gateway + sectionName: http + hostnames: + - my-filter.example.com + rules: + - filters: + - type: RequestRedirect + requestRedirect: + path: + type: ReplaceFullPath + replaceFullPath: /foo diff --git a/examples/experimental/v1alpha2/http-rewrite.yaml b/examples/experimental/v1alpha2/http-rewrite.yaml new file mode 100644 index 0000000000..fa61b8064e --- /dev/null +++ b/examples/experimental/v1alpha2/http-rewrite.yaml @@ -0,0 +1,18 @@ +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: http-filter-1 + namespace: gateway-api-example-ns1 +spec: + parentRefs: + - name: my-filter-gateway + sectionName: http + hostnames: + - my-filter.example.com + rules: + - filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplaceFullPath + replaceFullPath: /foo diff --git a/examples/experimental/v1alpha2/traffic-matching-tcp.yaml b/examples/experimental/v1alpha2/traffic-matching-tcp.yaml deleted file mode 100644 index 0d5095640a..0000000000 --- a/examples/experimental/v1alpha2/traffic-matching-tcp.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: gateway.networking.k8s.io/v1alpha2 -kind: TCPRoute -metadata: - name: traffic-matching-example -spec: - rules: - - matches: - - sourceAddresses: - - value: "192.168.1.1" - - value: "FE80::0202:B3FF:FE1E:8329" - destinationAddresses: - - value: "10.96.0.1" - backendRefs: - - name: my-service - port: 8080 diff --git a/examples/v1alpha1/basic-http.yaml b/examples/v1alpha1/basic-http.yaml index 23bc658901..8a39eae346 100644 --- a/examples/v1alpha1/basic-http.yaml +++ b/examples/v1alpha1/basic-http.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/api-types/httproute.md apiVersion: networking.x-k8s.io/v1alpha1 kind: GatewayClass metadata: diff --git a/examples/v1alpha1/basic-tcp.yaml b/examples/v1alpha1/basic-tcp.yaml index c403425820..31b02ddfc3 100644 --- a/examples/v1alpha1/basic-tcp.yaml +++ b/examples/v1alpha1/basic-tcp.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/tcp.md apiVersion: networking.x-k8s.io/v1alpha1 kind: GatewayClass metadata: diff --git a/examples/v1alpha1/cross-namespace-routing/gateway.yaml b/examples/v1alpha1/cross-namespace-routing/gateway.yaml index 88b9988c90..1ddc103224 100644 --- a/examples/v1alpha1/cross-namespace-routing/gateway.yaml +++ b/examples/v1alpha1/cross-namespace-routing/gateway.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/multiple-ns.md apiVersion: networking.x-k8s.io/v1alpha1 kind: Gateway metadata: diff --git a/examples/v1alpha1/cross-namespace-routing/site-route.yaml b/examples/v1alpha1/cross-namespace-routing/site-route.yaml index b0f797cfbf..fa10cf1f6e 100644 --- a/examples/v1alpha1/cross-namespace-routing/site-route.yaml +++ b/examples/v1alpha1/cross-namespace-routing/site-route.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/multiple-ns.md apiVersion: networking.x-k8s.io/v1alpha1 kind: HTTPRoute metadata: diff --git a/examples/v1alpha1/cross-namespace-routing/store-route.yaml b/examples/v1alpha1/cross-namespace-routing/store-route.yaml index 416c0e59a6..298dba72bf 100644 --- a/examples/v1alpha1/cross-namespace-routing/store-route.yaml +++ b/examples/v1alpha1/cross-namespace-routing/store-route.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/multiple-ns.md apiVersion: networking.x-k8s.io/v1alpha1 kind: HTTPRoute metadata: diff --git a/examples/v1alpha1/http-filter.yaml b/examples/v1alpha1/http-filter.yaml index a036e05652..18612b286e 100644 --- a/examples/v1alpha1/http-filter.yaml +++ b/examples/v1alpha1/http-filter.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/api-types/httproute.md apiVersion: networking.x-k8s.io/v1alpha1 kind: GatewayClass metadata: diff --git a/examples/v1alpha1/http-routing/bar-httproute.yaml b/examples/v1alpha1/http-routing/bar-httproute.yaml index bdc7ddc68d..1c30e02cbe 100644 --- a/examples/v1alpha1/http-routing/bar-httproute.yaml +++ b/examples/v1alpha1/http-routing/bar-httproute.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/http-routing.md apiVersion: networking.x-k8s.io/v1alpha1 kind: HTTPRoute metadata: diff --git a/examples/v1alpha1/http-routing/foo-httproute.yaml b/examples/v1alpha1/http-routing/foo-httproute.yaml index 0e1ab0f78e..e214ee485e 100644 --- a/examples/v1alpha1/http-routing/foo-httproute.yaml +++ b/examples/v1alpha1/http-routing/foo-httproute.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/http-routing.md apiVersion: networking.x-k8s.io/v1alpha1 kind: HTTPRoute metadata: diff --git a/examples/v1alpha1/http-routing/gateway.yaml b/examples/v1alpha1/http-routing/gateway.yaml index b099c706ac..b0c8fe82cf 100644 --- a/examples/v1alpha1/http-routing/gateway.yaml +++ b/examples/v1alpha1/http-routing/gateway.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/http-routing.md apiVersion: networking.x-k8s.io/v1alpha1 kind: Gateway metadata: diff --git a/examples/v1alpha1/http-trafficsplit.yaml b/examples/v1alpha1/http-trafficsplit.yaml index ccd1ad3775..ff5e856feb 100644 --- a/examples/v1alpha1/http-trafficsplit.yaml +++ b/examples/v1alpha1/http-trafficsplit.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/api-types/httproute.md apiVersion: networking.x-k8s.io/v1alpha1 kind: GatewayClass metadata: diff --git a/examples/v1alpha1/simple-gateway/gateway.yaml b/examples/v1alpha1/simple-gateway/gateway.yaml index b099c706ac..cd14656195 100644 --- a/examples/v1alpha1/simple-gateway/gateway.yaml +++ b/examples/v1alpha1/simple-gateway/gateway.yaml @@ -1,3 +1,6 @@ +## Used in: +## - site-src/v1alpha1/guides/traffic-splitting.md +## - site-src/v1alpha1/guides/simple-gateway.md apiVersion: networking.x-k8s.io/v1alpha1 kind: Gateway metadata: diff --git a/examples/v1alpha1/simple-gateway/httproute.yaml b/examples/v1alpha1/simple-gateway/httproute.yaml index 6f20bc6794..c77b66a7b2 100644 --- a/examples/v1alpha1/simple-gateway/httproute.yaml +++ b/examples/v1alpha1/simple-gateway/httproute.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/simple-gateway.md apiVersion: networking.x-k8s.io/v1alpha1 kind: HTTPRoute metadata: diff --git a/examples/v1alpha1/tls-basic.yaml b/examples/v1alpha1/tls-basic.yaml index 6b8898e5c7..93824b834c 100644 --- a/examples/v1alpha1/tls-basic.yaml +++ b/examples/v1alpha1/tls-basic.yaml @@ -1,3 +1,6 @@ +## Used in: +## - site-src/v1alpha1/guides/tls.md +## - site-src/v1alpha1/api-types/httproute.md apiVersion: networking.x-k8s.io/v1alpha1 kind: Gateway metadata: diff --git a/examples/v1alpha1/tls-cert-in-route.yaml b/examples/v1alpha1/tls-cert-in-route.yaml index d763652423..1ca6a9ba3b 100644 --- a/examples/v1alpha1/tls-cert-in-route.yaml +++ b/examples/v1alpha1/tls-cert-in-route.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/tls.md apiVersion: networking.x-k8s.io/v1alpha1 kind: Gateway metadata: diff --git a/examples/v1alpha1/traffic-splitting/simple-split.yaml b/examples/v1alpha1/traffic-splitting/simple-split.yaml index 3bf813eaca..bf80bfc4c4 100644 --- a/examples/v1alpha1/traffic-splitting/simple-split.yaml +++ b/examples/v1alpha1/traffic-splitting/simple-split.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/traffic-splitting.md apiVersion: networking.x-k8s.io/v1alpha1 kind: HTTPRoute metadata: diff --git a/examples/v1alpha1/traffic-splitting/traffic-split-1.yaml b/examples/v1alpha1/traffic-splitting/traffic-split-1.yaml index 8c5e2cdd2d..734e45c7ef 100644 --- a/examples/v1alpha1/traffic-splitting/traffic-split-1.yaml +++ b/examples/v1alpha1/traffic-splitting/traffic-split-1.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/traffic-splitting.md apiVersion: networking.x-k8s.io/v1alpha1 kind: HTTPRoute metadata: diff --git a/examples/v1alpha1/traffic-splitting/traffic-split-2.yaml b/examples/v1alpha1/traffic-splitting/traffic-split-2.yaml index 0e69b4da4e..e9751e92a9 100644 --- a/examples/v1alpha1/traffic-splitting/traffic-split-2.yaml +++ b/examples/v1alpha1/traffic-splitting/traffic-split-2.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/traffic-splitting.md apiVersion: networking.x-k8s.io/v1alpha1 kind: HTTPRoute metadata: diff --git a/examples/v1alpha1/traffic-splitting/traffic-split-3.yaml b/examples/v1alpha1/traffic-splitting/traffic-split-3.yaml index 879374891b..ba4367c810 100644 --- a/examples/v1alpha1/traffic-splitting/traffic-split-3.yaml +++ b/examples/v1alpha1/traffic-splitting/traffic-split-3.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/traffic-splitting.md apiVersion: networking.x-k8s.io/v1alpha1 kind: HTTPRoute metadata: diff --git a/examples/v1alpha1/upstream-tls.yaml b/examples/v1alpha1/upstream-tls.yaml index 59ea9e4da1..aad4bb2346 100644 --- a/examples/v1alpha1/upstream-tls.yaml +++ b/examples/v1alpha1/upstream-tls.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/tls.md apiVersion: networking.x-k8s.io/v1alpha1 kind: BackendPolicy metadata: diff --git a/examples/v1alpha1/wildcard-tls-gateway.yaml b/examples/v1alpha1/wildcard-tls-gateway.yaml index b30702ffcc..7d7435a2f3 100644 --- a/examples/v1alpha1/wildcard-tls-gateway.yaml +++ b/examples/v1alpha1/wildcard-tls-gateway.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha1/guides/tls.md apiVersion: networking.x-k8s.io/v1alpha1 kind: Gateway metadata: diff --git a/examples/v1alpha2/basic-http.yaml b/examples/v1alpha2/basic-http.yaml index dfdf9a78d1..a6386ed35f 100644 --- a/examples/v1alpha2/basic-http.yaml +++ b/examples/v1alpha2/basic-http.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/api-types/httproute.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: GatewayClass metadata: diff --git a/examples/v1alpha2/basic-tcp.yaml b/examples/v1alpha2/basic-tcp.yaml index 0cb49ec75b..45682892e2 100644 --- a/examples/v1alpha2/basic-tcp.yaml +++ b/examples/v1alpha2/basic-tcp.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/tcp.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: diff --git a/examples/v1alpha2/cross-namespace-routing/0-namespaces.yaml b/examples/v1alpha2/cross-namespace-routing/0-namespaces.yaml index bab5690750..80d05a7f17 100644 --- a/examples/v1alpha2/cross-namespace-routing/0-namespaces.yaml +++ b/examples/v1alpha2/cross-namespace-routing/0-namespaces.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/multiple-ns.md apiVersion: v1 kind: Namespace metadata: diff --git a/examples/v1alpha2/cross-namespace-routing/gateway.yaml b/examples/v1alpha2/cross-namespace-routing/gateway.yaml index 049f59365f..44108e1378 100644 --- a/examples/v1alpha2/cross-namespace-routing/gateway.yaml +++ b/examples/v1alpha2/cross-namespace-routing/gateway.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/multiple-ns.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: diff --git a/examples/v1alpha2/cross-namespace-routing/site-route.yaml b/examples/v1alpha2/cross-namespace-routing/site-route.yaml index 885e98cd7e..e208ac3e87 100644 --- a/examples/v1alpha2/cross-namespace-routing/site-route.yaml +++ b/examples/v1alpha2/cross-namespace-routing/site-route.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/multiple-ns.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: diff --git a/examples/v1alpha2/cross-namespace-routing/store-route.yaml b/examples/v1alpha2/cross-namespace-routing/store-route.yaml index 03d411c8e6..1da7225dc9 100644 --- a/examples/v1alpha2/cross-namespace-routing/store-route.yaml +++ b/examples/v1alpha2/cross-namespace-routing/store-route.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/multiple-ns.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: diff --git a/examples/v1alpha2/http-filter.yaml b/examples/v1alpha2/http-filter.yaml index 541db904d0..831bd7fd16 100644 --- a/examples/v1alpha2/http-filter.yaml +++ b/examples/v1alpha2/http-filter.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/api-types/httproute.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: diff --git a/examples/v1alpha2/http-route-attachment/gateway-namespaces.yaml b/examples/v1alpha2/http-route-attachment/gateway-namespaces.yaml index eb7e5c2f46..0f8c33b1f9 100644 --- a/examples/v1alpha2/http-route-attachment/gateway-namespaces.yaml +++ b/examples/v1alpha2/http-route-attachment/gateway-namespaces.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/concepts/api-overview.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: diff --git a/examples/v1alpha2/http-route-attachment/gateway-strict.yaml b/examples/v1alpha2/http-route-attachment/gateway-strict.yaml index 8d518c9bd2..3fe75bbbc5 100644 --- a/examples/v1alpha2/http-route-attachment/gateway-strict.yaml +++ b/examples/v1alpha2/http-route-attachment/gateway-strict.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/concepts/api-overview.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: diff --git a/examples/v1alpha2/http-route-attachment/httproute.yaml b/examples/v1alpha2/http-route-attachment/httproute.yaml index f0cc853dbe..06e49da04e 100644 --- a/examples/v1alpha2/http-route-attachment/httproute.yaml +++ b/examples/v1alpha2/http-route-attachment/httproute.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/concepts/api-overview.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: diff --git a/examples/v1alpha2/http-routing/bar-httproute.yaml b/examples/v1alpha2/http-routing/bar-httproute.yaml index 633c42980f..2483f74ad1 100644 --- a/examples/v1alpha2/http-routing/bar-httproute.yaml +++ b/examples/v1alpha2/http-routing/bar-httproute.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/http-routing.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: diff --git a/examples/v1alpha2/http-routing/foo-httproute.yaml b/examples/v1alpha2/http-routing/foo-httproute.yaml index a611719ce8..9a616c12b4 100644 --- a/examples/v1alpha2/http-routing/foo-httproute.yaml +++ b/examples/v1alpha2/http-routing/foo-httproute.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/http-routing.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: diff --git a/examples/v1alpha2/http-routing/gateway.yaml b/examples/v1alpha2/http-routing/gateway.yaml index ad3b30ea0d..4c7e4a858b 100644 --- a/examples/v1alpha2/http-routing/gateway.yaml +++ b/examples/v1alpha2/http-routing/gateway.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/http-routing.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: diff --git a/examples/v1alpha2/reference-policy.yaml b/examples/v1alpha2/reference-grant.yaml similarity index 63% rename from examples/v1alpha2/reference-policy.yaml rename to examples/v1alpha2/reference-grant.yaml index 3cb3fcbdf0..1c0d71b12b 100644 --- a/examples/v1alpha2/reference-policy.yaml +++ b/examples/v1alpha2/reference-grant.yaml @@ -1,5 +1,8 @@ +## Used in: +## - site-src/concepts/security-model.md +## - site-src/blog/2021/introducing-v1alpha2.md apiVersion: gateway.networking.k8s.io/v1alpha2 -kind: ReferencePolicy +kind: ReferenceGrant metadata: name: allow-prod-traffic spec: diff --git a/examples/v1alpha2/simple-gateway/gateway.yaml b/examples/v1alpha2/simple-gateway/gateway.yaml index 565ae1c7bc..00421fbd36 100644 --- a/examples/v1alpha2/simple-gateway/gateway.yaml +++ b/examples/v1alpha2/simple-gateway/gateway.yaml @@ -1,3 +1,6 @@ +## Used in: +## - site-src/v1alpha2/guides/traffic-splitting.md +## - site-src/v1alpha2/guides/simple-gateway.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: diff --git a/examples/v1alpha2/simple-gateway/httproute.yaml b/examples/v1alpha2/simple-gateway/httproute.yaml index 25ee8f6327..7e6e70219d 100644 --- a/examples/v1alpha2/simple-gateway/httproute.yaml +++ b/examples/v1alpha2/simple-gateway/httproute.yaml @@ -1,3 +1,6 @@ +## Used in: +## - site-src/v1alpha2/guides/simple-gateway.md +## - site-src/blog/2021/introducing-v1alpha2.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: diff --git a/examples/v1alpha2/tls-basic.yaml b/examples/v1alpha2/tls-basic.yaml index 2827df2fee..b1a0f7e45c 100644 --- a/examples/v1alpha2/tls-basic.yaml +++ b/examples/v1alpha2/tls-basic.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/tls.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: diff --git a/examples/v1alpha2/tls-cert-cross-namespace.yaml b/examples/v1alpha2/tls-cert-cross-namespace.yaml index da6aa71f90..156fa42b7d 100644 --- a/examples/v1alpha2/tls-cert-cross-namespace.yaml +++ b/examples/v1alpha2/tls-cert-cross-namespace.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/tls.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: @@ -18,7 +20,7 @@ spec: namespace: gateway-api-example-ns2 --- apiVersion: gateway.networking.k8s.io/v1alpha2 -kind: ReferencePolicy +kind: ReferenceGrant metadata: name: allow-ns1-gateways-to-ref-secrets namespace: gateway-api-example-ns2 diff --git a/examples/v1alpha2/traffic-splitting/simple-split.yaml b/examples/v1alpha2/traffic-splitting/simple-split.yaml index 981dd8e753..0f139f31de 100644 --- a/examples/v1alpha2/traffic-splitting/simple-split.yaml +++ b/examples/v1alpha2/traffic-splitting/simple-split.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/traffic-splitting.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: diff --git a/examples/v1alpha2/traffic-splitting/traffic-split-1.yaml b/examples/v1alpha2/traffic-splitting/traffic-split-1.yaml index d95b4dabbf..dbddfe9d49 100644 --- a/examples/v1alpha2/traffic-splitting/traffic-split-1.yaml +++ b/examples/v1alpha2/traffic-splitting/traffic-split-1.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/traffic-splitting.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: diff --git a/examples/v1alpha2/traffic-splitting/traffic-split-2.yaml b/examples/v1alpha2/traffic-splitting/traffic-split-2.yaml index 5794d55fac..fec7119576 100644 --- a/examples/v1alpha2/traffic-splitting/traffic-split-2.yaml +++ b/examples/v1alpha2/traffic-splitting/traffic-split-2.yaml @@ -1,3 +1,6 @@ +## Used in: +## - site-src/v1alpha2/guides/traffic-splitting.md +## - site-src/v1alpha2/api-types/httproute.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: diff --git a/examples/v1alpha2/traffic-splitting/traffic-split-3.yaml b/examples/v1alpha2/traffic-splitting/traffic-split-3.yaml index 6da146619f..2e34bc9d76 100644 --- a/examples/v1alpha2/traffic-splitting/traffic-split-3.yaml +++ b/examples/v1alpha2/traffic-splitting/traffic-split-3.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/traffic-splitting.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: diff --git a/examples/v1alpha2/wildcard-tls-gateway.yaml b/examples/v1alpha2/wildcard-tls-gateway.yaml index 7d4bcb46e6..6504119a3a 100644 --- a/examples/v1alpha2/wildcard-tls-gateway.yaml +++ b/examples/v1alpha2/wildcard-tls-gateway.yaml @@ -1,3 +1,5 @@ +## Used in: +## - site-src/v1alpha2/guides/tls.md apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: diff --git a/go.mod b/go.mod index db745cd14e..f513e63a0f 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,12 @@ module sigs.k8s.io/gateway-api -go 1.17 +go 1.18 require ( github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 github.com/lithammer/dedent v1.1.0 - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/stretchr/testify v1.7.0 + golang.org/x/exp v0.0.0-20220407100705-7b9b53b0aca4 k8s.io/api v0.22.4 k8s.io/apiextensions-apiserver v0.22.4 k8s.io/apimachinery v0.22.4 @@ -47,17 +47,18 @@ require ( github.com/modern-go/reflect2 v1.0.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spf13/cobra v1.2.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect - golang.org/x/mod v0.4.2 // indirect - golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect + golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 // indirect + golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 // indirect - golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 // indirect + golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect - golang.org/x/text v0.3.6 // indirect + golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect - golang.org/x/tools v0.1.5 // indirect + golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.26.0 // indirect diff --git a/go.sum b/go.sum index 00bb8cf036..f7f0a145b9 100644 --- a/go.sum +++ b/go.sum @@ -38,22 +38,18 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= @@ -81,6 +77,7 @@ github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiU github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= @@ -89,7 +86,9 @@ github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -98,22 +97,17 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -122,7 +116,6 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -135,7 +128,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -163,16 +155,12 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/zapr v0.4.0 h1:uc1uML3hRYL9/ZZPdgHS/n8Nzo+eaYL/Efxkkamf7OM= github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -186,7 +174,6 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -252,26 +239,21 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= @@ -288,7 +270,6 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= @@ -308,7 +289,6 @@ github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUB github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -328,7 +308,6 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -338,17 +317,15 @@ github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -361,7 +338,6 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -380,19 +356,15 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.14.0 h1:ep6kpPVwmr/nTbklSx2nrLNSIO62DoYAhnPNIMhK8gI= github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= @@ -414,21 +386,24 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -455,15 +430,12 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -472,7 +444,6 @@ github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -481,10 +452,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -492,10 +461,7 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= @@ -522,28 +488,29 @@ go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -554,6 +521,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20220407100705-7b9b53b0aca4 h1:K3x+yU+fbot38x5bQbU2QqUAVyYLEktdNH2GxZLnM3U= +golang.org/x/exp v0.0.0-20220407100705-7b9b53b0aca4/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -576,11 +545,11 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 h1:LQmS1nU0twXLA96Kt7U9qtHJEbBk3z6Q0V4UXjZkpr4= +golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -599,7 +568,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -622,13 +590,13 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 h1:ADo5wSpq2gqaCGQWzk7S5vd//0iyyLeAratkEoG5dLE= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -667,10 +635,8 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -713,14 +679,12 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo= golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= @@ -732,9 +696,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -754,7 +718,6 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -799,13 +762,15 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023 h1:0c3L82FDQ5rt1bjTBlchS8t6RQ6299/+5bWMnRLh+uI= +golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -871,7 +836,6 @@ google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -921,7 +885,6 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= @@ -956,30 +919,23 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg= k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= k8s.io/api v0.22.4 h1:UvyHW0ezB2oIgHAxlYoo6UJQObYXU7awuNarwoHEOjw= k8s.io/api v0.22.4/go.mod h1:Rgs+9gIGYC5laXQSZZ9JqT5NevNgoGiOdVWi1BAB3qk= -k8s.io/apiextensions-apiserver v0.21.3/go.mod h1:kl6dap3Gd45+21Jnh6utCx8Z2xxLm8LGDkprcd+KbsE= k8s.io/apiextensions-apiserver v0.22.2/go.mod h1:2E0Ve/isxNl7tWLSUDgi6+cmwHi5fQRdwGVCxbC+KFA= k8s.io/apiextensions-apiserver v0.22.4 h1:2iGpcVyw4MnAyyXVJU2Xg6ZsbIxAOfRHo0LF5A5J0RA= k8s.io/apiextensions-apiserver v0.22.4/go.mod h1:kH9lxD8dbJ+k0ZizGET55lFgdGjO8t45fgZnCVdZEpw= -k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI= k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= k8s.io/apimachinery v0.22.4 h1:9uwcvPpukBw/Ri0EUmWz+49cnFtaoiyEhQTK+xOe7Ck= k8s.io/apimachinery v0.22.4/go.mod h1:yU6oA6Gnax9RrxGzVvPFFJ+mpnW6PBSqp0sx0I0HHW0= -k8s.io/apiserver v0.21.3/go.mod h1:eDPWlZG6/cCCMj/JBcEpDoK+I+6i3r9GsChYBHSbAzU= k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI= k8s.io/apiserver v0.22.4/go.mod h1:38WmcUZiiy41A7Aty8/VorWRa8vDGqoUzDf2XYlku0E= -k8s.io/client-go v0.21.3/go.mod h1:+VPhCgTsaFmGILxR/7E1N0S+ryO010QBeNCv5JwRGYU= k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= k8s.io/client-go v0.22.4 h1:aAQ1Wk+I3bjCNk35YWUqbaueqrIonkfDPJSPDDe8Kfg= k8s.io/client-go v0.22.4/go.mod h1:Yzw4e5e7h1LNHA4uqnMVrpEpUs1hJOiuBsJKIlRCHDA= -k8s.io/code-generator v0.21.3/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo= k8s.io/code-generator v0.22.2/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= k8s.io/code-generator v0.22.4 h1:h7lBa5IuEUC4OQ45q/gIip/a0iQcML2iwrRmXksau30= k8s.io/code-generator v0.22.4/go.mod h1:qjYl54pQ/emhkT0UxbufbREYJMWsHNNV/jSVwhYZQGw= -k8s.io/component-base v0.21.3/go.mod h1:kkuhtfEHeZM6LkX0saqSK8PbdO7A0HigUngmhhrwfGQ= k8s.io/component-base v0.22.2/go.mod h1:5Br2QhI9OTe79p+TzPe9JKNQYvEKbq9rTJDWllunGug= k8s.io/component-base v0.22.4/go.mod h1:MrSaQy4a3tFVViff8TZL6JHYSewNCLshZCwHYM58v5A= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= @@ -990,26 +946,19 @@ k8s.io/klog v0.2.0 h1:0ElL0OHzF3N+OhoJTL0uca20SxtYt4X4+bzHeqrB83c= k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.10.0 h1:R2HDMDJsHVTHA2n4RjwbeYXdOcBymXdX/JRb1v0VGhE= k8s.io/klog/v2 v2.10.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c h1:jvamsI1tn9V0S8jicyX82qaFC0H/NKxv2e5mbqsgR80= k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210722164352-7f3ee0f31471/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e h1:ldQh+neBabomh7+89dTpiFAB8tGdfVmuIzAHbvtl+9I= k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/controller-runtime v0.9.6 h1:EevVMlgUj4fC1NVM4+DB3iPkWkmGRNarA66neqv9Qew= -sigs.k8s.io/controller-runtime v0.9.6/go.mod h1:q6PpkM5vqQubEKUKOM6qr06oXGzOBcCby1DA9FbyZeA= sigs.k8s.io/controller-runtime v0.10.3 h1:s5Ttmw/B4AuIbwrXD3sfBkXwnPMMWrqpVj4WRt1dano= sigs.k8s.io/controller-runtime v0.10.3/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY= sigs.k8s.io/controller-tools v0.7.0 h1:iZIz1vEcavyEfxjcTLs1WH/MPf4vhPCtTKhoHqV8/G0= @@ -1017,6 +966,5 @@ sigs.k8s.io/controller-tools v0.7.0/go.mod h1:bpBAo0VcSDDLuWt47evLhMLPxRPxMDInTE sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/hack/boilerplate/boilerplate.py b/hack/boilerplate/boilerplate.py index 60bc691a8f..9c0161862b 100755 --- a/hack/boilerplate/boilerplate.py +++ b/hack/boilerplate/boilerplate.py @@ -248,6 +248,8 @@ def main(): if not file_passes(filename, refs, regexs): print(filename, file=sys.stdout) + print("Verified %d file headers match boilerplate" % (len(filenames),), file=sys.stderr) + return 0 diff --git a/hack/build-install-yaml.sh b/hack/build-install-yaml.sh new file mode 100755 index 0000000000..8a20a055bd --- /dev/null +++ b/hack/build-install-yaml.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# 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. + +set -o errexit +set -o nounset +set -o pipefail + +thisyear=`date +"%Y"` + +mkdir -p release/ + +# Make clean files with boilerplate +cat hack/boilerplate/boilerplate.sh.txt > release/experimental-install.yaml +sed -i "s/YEAR/$thisyear/g" release/experimental-install.yaml +cat << EOF >> release/experimental-install.yaml +# +# Gateway API Experimental channel install +# +EOF + +cat hack/boilerplate/boilerplate.sh.txt > release/stable-install.yaml +sed -i "s/YEAR/$thisyear/g" release/stable-install.yaml +cat << EOF >> release/stable-install.yaml +# +# Gateway API Stable channel install +# +EOF + +for file in `ls config/webhook/*.yaml config/crd/experimental/*.yaml` +do + echo "---" >> release/experimental-install.yaml + echo "#" >> release/experimental-install.yaml + echo "# $file" >> release/experimental-install.yaml + echo "#" >> release/experimental-install.yaml + cat $file >> release/experimental-install.yaml +done + +for file in `ls config/webhook/*.yaml config/crd/stable/*.yaml` +do + echo "---" >> release/stable-install.yaml + echo "#" >> release/stable-install.yaml + echo "# $file" >> release/stable-install.yaml + echo "#" >> release/stable-install.yaml + cat $file >> release/stable-install.yaml +done + +echo "Generated:" release/*-install.yaml diff --git a/hack/invalid-examples/v1alpha2/referencepolicy/missing-from.yaml b/hack/invalid-examples/v1alpha2/referencegrant/missing-from.yaml similarity index 84% rename from hack/invalid-examples/v1alpha2/referencepolicy/missing-from.yaml rename to hack/invalid-examples/v1alpha2/referencegrant/missing-from.yaml index 628a70d850..928c17b41c 100644 --- a/hack/invalid-examples/v1alpha2/referencepolicy/missing-from.yaml +++ b/hack/invalid-examples/v1alpha2/referencegrant/missing-from.yaml @@ -1,5 +1,5 @@ apiVersion: gateway.networking.k8s.io/v1alpha2 -kind: ReferencePolicy +kind: ReferenceGrant metadata: name: missing-from spec: diff --git a/hack/invalid-examples/v1alpha2/referencepolicy/missing-ns.yaml b/hack/invalid-examples/v1alpha2/referencegrant/missing-ns.yaml similarity index 89% rename from hack/invalid-examples/v1alpha2/referencepolicy/missing-ns.yaml rename to hack/invalid-examples/v1alpha2/referencegrant/missing-ns.yaml index cb681340ea..9619f3730e 100644 --- a/hack/invalid-examples/v1alpha2/referencepolicy/missing-ns.yaml +++ b/hack/invalid-examples/v1alpha2/referencegrant/missing-ns.yaml @@ -1,5 +1,5 @@ apiVersion: gateway.networking.k8s.io/v1alpha2 -kind: ReferencePolicy +kind: ReferenceGrant metadata: name: missing-ns spec: diff --git a/hack/invalid-examples/v1alpha2/referencepolicy/missing-to.yaml b/hack/invalid-examples/v1alpha2/referencegrant/missing-to.yaml similarity index 87% rename from hack/invalid-examples/v1alpha2/referencepolicy/missing-to.yaml rename to hack/invalid-examples/v1alpha2/referencegrant/missing-to.yaml index df8a8eabf0..b5ce8c54ba 100644 --- a/hack/invalid-examples/v1alpha2/referencepolicy/missing-to.yaml +++ b/hack/invalid-examples/v1alpha2/referencegrant/missing-to.yaml @@ -1,5 +1,5 @@ apiVersion: gateway.networking.k8s.io/v1alpha2 -kind: ReferencePolicy +kind: ReferenceGrant metadata: name: missing-to spec: diff --git a/hack/update-webhook-yaml.sh b/hack/update-webhook-yaml.sh new file mode 100755 index 0000000000..dc6e754f6b --- /dev/null +++ b/hack/update-webhook-yaml.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# 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. + +# This script is intended to be run by a human, not by Prow, so we +# err on the side of doing nothing if you don't have an exact semver +# BASE_REF + +set -o errexit +set -o nounset +set -o pipefail + +if [[ -z "${BASE_REF-}" ]]; +then + echo "BASE_REF env var must be set and nonempty." + exit 1 +fi + +semver='^v[0-9]+\.[0-9]+\.[0-9]+$' + +if [[ "${BASE_REF}" =~ $semver ]] +then + echo "Working on semver, need to replace." + for yaml in `ls config/webhook/*.yaml` + do + sed -i "s/:latest/:${BASE_REF}/g" $yaml + done +else + echo "No version requested with BASE_REF, nothing to do." +fi + diff --git a/hack/verify-examples-kind.sh b/hack/verify-examples-kind.sh index b975b8782c..c446a10789 100755 --- a/hack/verify-examples-kind.sh +++ b/hack/verify-examples-kind.sh @@ -25,7 +25,7 @@ readonly CLUSTER_NAME="verify-gateway-api" export KUBECONFIG="${GOPATH}/.kubeconfig" export GOFLAGS GO111MODULE GOPATH -export PATH="${PATH}:${GOPATH}/bin" +export PATH="${GOPATH}/bin:${PATH}" # Cleanup logic for cleanup on exit CLEANED_UP=false @@ -53,7 +53,7 @@ kind create cluster --name "${CLUSTER_NAME}" || res=$? # Install webhook docker build -t gcr.io/k8s-staging-gateway-api/admission-server:latest . -kubectl apply -f deploy/ +kubectl apply -f config/webhook/ # Wait for webhook to be ready for check in {1..10}; do diff --git a/hack/verify-golint.sh b/hack/verify-golint.sh index 96d3329bdc..3822e42b0b 100755 --- a/hack/verify-golint.sh +++ b/hack/verify-golint.sh @@ -18,7 +18,7 @@ set -o errexit set -o nounset set -o pipefail -readonly VERSION="v1.43.0" +readonly VERSION="v1.46.2" readonly KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. cd "${KUBE_ROOT}" diff --git a/mkdocs.yml b/mkdocs.yml index 6ad75da40c..737d577ea0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -21,6 +21,7 @@ plugins: - awesome-pages - macros: include_dir: examples + j2_line_comment_prefix: "##" markdown_extensions: - admonition - meta @@ -66,7 +67,7 @@ nav: GatewayClass: v1alpha2/api-types/gatewayclass.md Gateway: v1alpha2/api-types/gateway.md HTTPRoute: v1alpha2/api-types/httproute.md - ReferencePolicy: v1alpha2/api-types/referencepolicy.md + ReferenceGrant: v1alpha2/api-types/referencegrant.md - API specification: v1alpha2/references/spec.md - Policy Attachment: v1alpha2/references/policy-attachment.md - v1alpha1: @@ -78,7 +79,6 @@ nav: - Enhancement Proposals: - Overview: contributing/gep.md - ... | geps/gep-*.md - - Release policy: references/releases.md - Contributing: - Developer guide: contributing/devguide.md - Enhancement Tracking and Backlog: contributing/enhancement-requests.md 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 05747312a8..604504621f 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha2/apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/apis_client.go @@ -29,7 +29,7 @@ type GatewayV1alpha2Interface interface { GatewaysGetter GatewayClassesGetter HTTPRoutesGetter - ReferencePoliciesGetter + ReferenceGrantsGetter TCPRoutesGetter TLSRoutesGetter UDPRoutesGetter @@ -52,8 +52,8 @@ func (c *GatewayV1alpha2Client) HTTPRoutes(namespace string) HTTPRouteInterface return newHTTPRoutes(c, namespace) } -func (c *GatewayV1alpha2Client) ReferencePolicies(namespace string) ReferencePolicyInterface { - return newReferencePolicies(c, namespace) +func (c *GatewayV1alpha2Client) ReferenceGrants(namespace string) ReferenceGrantInterface { + return newReferenceGrants(c, namespace) } func (c *GatewayV1alpha2Client) TCPRoutes(namespace string) TCPRouteInterface { 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 4bed16a91f..f1e58b0b02 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 @@ -40,8 +40,8 @@ func (c *FakeGatewayV1alpha2) HTTPRoutes(namespace string) v1alpha2.HTTPRouteInt return &FakeHTTPRoutes{c, namespace} } -func (c *FakeGatewayV1alpha2) ReferencePolicies(namespace string) v1alpha2.ReferencePolicyInterface { - return &FakeReferencePolicies{c, namespace} +func (c *FakeGatewayV1alpha2) ReferenceGrants(namespace string) v1alpha2.ReferenceGrantInterface { + return &FakeReferenceGrants{c, namespace} } func (c *FakeGatewayV1alpha2) TCPRoutes(namespace string) v1alpha2.TCPRouteInterface { diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_referencegrant.go b/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_referencegrant.go new file mode 100644 index 0000000000..7c4c5b6c5d --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_referencegrant.go @@ -0,0 +1,130 @@ +/* +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" +) + +// FakeReferenceGrants implements ReferenceGrantInterface +type FakeReferenceGrants struct { + Fake *FakeGatewayV1alpha2 + ns string +} + +var referencegrantsResource = schema.GroupVersionResource{Group: "gateway.networking.k8s.io", Version: "v1alpha2", Resource: "referencegrants"} + +var referencegrantsKind = schema.GroupVersionKind{Group: "gateway.networking.k8s.io", Version: "v1alpha2", Kind: "ReferenceGrant"} + +// Get takes name of the referenceGrant, and returns the corresponding referenceGrant object, and an error if there is any. +func (c *FakeReferenceGrants) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.ReferenceGrant, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(referencegrantsResource, c.ns, name), &v1alpha2.ReferenceGrant{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.ReferenceGrant), err +} + +// List takes label and field selectors, and returns the list of ReferenceGrants that match those selectors. +func (c *FakeReferenceGrants) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.ReferenceGrantList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(referencegrantsResource, referencegrantsKind, c.ns, opts), &v1alpha2.ReferenceGrantList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha2.ReferenceGrantList{ListMeta: obj.(*v1alpha2.ReferenceGrantList).ListMeta} + for _, item := range obj.(*v1alpha2.ReferenceGrantList).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 referenceGrants. +func (c *FakeReferenceGrants) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(referencegrantsResource, c.ns, opts)) + +} + +// Create takes the representation of a referenceGrant and creates it. Returns the server's representation of the referenceGrant, and an error, if there is any. +func (c *FakeReferenceGrants) Create(ctx context.Context, referenceGrant *v1alpha2.ReferenceGrant, opts v1.CreateOptions) (result *v1alpha2.ReferenceGrant, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(referencegrantsResource, c.ns, referenceGrant), &v1alpha2.ReferenceGrant{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.ReferenceGrant), err +} + +// Update takes the representation of a referenceGrant and updates it. Returns the server's representation of the referenceGrant, and an error, if there is any. +func (c *FakeReferenceGrants) Update(ctx context.Context, referenceGrant *v1alpha2.ReferenceGrant, opts v1.UpdateOptions) (result *v1alpha2.ReferenceGrant, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(referencegrantsResource, c.ns, referenceGrant), &v1alpha2.ReferenceGrant{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.ReferenceGrant), err +} + +// Delete takes name of the referenceGrant and deletes it. Returns an error if one occurs. +func (c *FakeReferenceGrants) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(referencegrantsResource, c.ns, name), &v1alpha2.ReferenceGrant{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeReferenceGrants) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(referencegrantsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha2.ReferenceGrantList{}) + return err +} + +// Patch applies the patch and returns the patched referenceGrant. +func (c *FakeReferenceGrants) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.ReferenceGrant, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(referencegrantsResource, c.ns, name, pt, data, subresources...), &v1alpha2.ReferenceGrant{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.ReferenceGrant), err +} diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_referencepolicy.go b/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_referencepolicy.go deleted file mode 100644 index 414a985f2c..0000000000 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_referencepolicy.go +++ /dev/null @@ -1,130 +0,0 @@ -/* -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" -) - -// FakeReferencePolicies implements ReferencePolicyInterface -type FakeReferencePolicies struct { - Fake *FakeGatewayV1alpha2 - ns string -} - -var referencepoliciesResource = schema.GroupVersionResource{Group: "gateway.networking.k8s.io", Version: "v1alpha2", Resource: "referencepolicies"} - -var referencepoliciesKind = schema.GroupVersionKind{Group: "gateway.networking.k8s.io", Version: "v1alpha2", Kind: "ReferencePolicy"} - -// Get takes name of the referencePolicy, and returns the corresponding referencePolicy object, and an error if there is any. -func (c *FakeReferencePolicies) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.ReferencePolicy, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(referencepoliciesResource, c.ns, name), &v1alpha2.ReferencePolicy{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.ReferencePolicy), err -} - -// List takes label and field selectors, and returns the list of ReferencePolicies that match those selectors. -func (c *FakeReferencePolicies) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.ReferencePolicyList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(referencepoliciesResource, referencepoliciesKind, c.ns, opts), &v1alpha2.ReferencePolicyList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha2.ReferencePolicyList{ListMeta: obj.(*v1alpha2.ReferencePolicyList).ListMeta} - for _, item := range obj.(*v1alpha2.ReferencePolicyList).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 referencePolicies. -func (c *FakeReferencePolicies) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(referencepoliciesResource, c.ns, opts)) - -} - -// Create takes the representation of a referencePolicy and creates it. Returns the server's representation of the referencePolicy, and an error, if there is any. -func (c *FakeReferencePolicies) Create(ctx context.Context, referencePolicy *v1alpha2.ReferencePolicy, opts v1.CreateOptions) (result *v1alpha2.ReferencePolicy, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(referencepoliciesResource, c.ns, referencePolicy), &v1alpha2.ReferencePolicy{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.ReferencePolicy), err -} - -// Update takes the representation of a referencePolicy and updates it. Returns the server's representation of the referencePolicy, and an error, if there is any. -func (c *FakeReferencePolicies) Update(ctx context.Context, referencePolicy *v1alpha2.ReferencePolicy, opts v1.UpdateOptions) (result *v1alpha2.ReferencePolicy, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(referencepoliciesResource, c.ns, referencePolicy), &v1alpha2.ReferencePolicy{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.ReferencePolicy), err -} - -// Delete takes name of the referencePolicy and deletes it. Returns an error if one occurs. -func (c *FakeReferencePolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteAction(referencepoliciesResource, c.ns, name), &v1alpha2.ReferencePolicy{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeReferencePolicies) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(referencepoliciesResource, c.ns, listOpts) - - _, err := c.Fake.Invokes(action, &v1alpha2.ReferencePolicyList{}) - return err -} - -// Patch applies the patch and returns the patched referencePolicy. -func (c *FakeReferencePolicies) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.ReferencePolicy, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(referencepoliciesResource, c.ns, name, pt, data, subresources...), &v1alpha2.ReferencePolicy{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.ReferencePolicy), 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 bf9c1d9718..96b653b9d5 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha2/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/generated_expansion.go @@ -24,7 +24,7 @@ type GatewayClassExpansion interface{} type HTTPRouteExpansion interface{} -type ReferencePolicyExpansion interface{} +type ReferenceGrantExpansion interface{} type TCPRouteExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha2/referencepolicy.go b/pkg/client/clientset/versioned/typed/apis/v1alpha2/referencegrant.go similarity index 50% rename from pkg/client/clientset/versioned/typed/apis/v1alpha2/referencepolicy.go rename to pkg/client/clientset/versioned/typed/apis/v1alpha2/referencegrant.go index f3e784c417..954fb6a248 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha2/referencepolicy.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/referencegrant.go @@ -30,45 +30,45 @@ import ( scheme "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/scheme" ) -// ReferencePoliciesGetter has a method to return a ReferencePolicyInterface. +// ReferenceGrantsGetter has a method to return a ReferenceGrantInterface. // A group's client should implement this interface. -type ReferencePoliciesGetter interface { - ReferencePolicies(namespace string) ReferencePolicyInterface +type ReferenceGrantsGetter interface { + ReferenceGrants(namespace string) ReferenceGrantInterface } -// ReferencePolicyInterface has methods to work with ReferencePolicy resources. -type ReferencePolicyInterface interface { - Create(ctx context.Context, referencePolicy *v1alpha2.ReferencePolicy, opts v1.CreateOptions) (*v1alpha2.ReferencePolicy, error) - Update(ctx context.Context, referencePolicy *v1alpha2.ReferencePolicy, opts v1.UpdateOptions) (*v1alpha2.ReferencePolicy, error) +// ReferenceGrantInterface has methods to work with ReferenceGrant resources. +type ReferenceGrantInterface interface { + Create(ctx context.Context, referenceGrant *v1alpha2.ReferenceGrant, opts v1.CreateOptions) (*v1alpha2.ReferenceGrant, error) + Update(ctx context.Context, referenceGrant *v1alpha2.ReferenceGrant, opts v1.UpdateOptions) (*v1alpha2.ReferenceGrant, 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.ReferencePolicy, error) - List(ctx context.Context, opts v1.ListOptions) (*v1alpha2.ReferencePolicyList, error) + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha2.ReferenceGrant, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha2.ReferenceGrantList, 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.ReferencePolicy, err error) - ReferencePolicyExpansion + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.ReferenceGrant, err error) + ReferenceGrantExpansion } -// referencePolicies implements ReferencePolicyInterface -type referencePolicies struct { +// referenceGrants implements ReferenceGrantInterface +type referenceGrants struct { client rest.Interface ns string } -// newReferencePolicies returns a ReferencePolicies -func newReferencePolicies(c *GatewayV1alpha2Client, namespace string) *referencePolicies { - return &referencePolicies{ +// newReferenceGrants returns a ReferenceGrants +func newReferenceGrants(c *GatewayV1alpha2Client, namespace string) *referenceGrants { + return &referenceGrants{ client: c.RESTClient(), ns: namespace, } } -// Get takes name of the referencePolicy, and returns the corresponding referencePolicy object, and an error if there is any. -func (c *referencePolicies) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.ReferencePolicy, err error) { - result = &v1alpha2.ReferencePolicy{} +// Get takes name of the referenceGrant, and returns the corresponding referenceGrant object, and an error if there is any. +func (c *referenceGrants) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.ReferenceGrant, err error) { + result = &v1alpha2.ReferenceGrant{} err = c.client.Get(). Namespace(c.ns). - Resource("referencepolicies"). + Resource("referencegrants"). Name(name). VersionedParams(&options, scheme.ParameterCodec). Do(ctx). @@ -76,16 +76,16 @@ func (c *referencePolicies) Get(ctx context.Context, name string, options v1.Get return } -// List takes label and field selectors, and returns the list of ReferencePolicies that match those selectors. -func (c *referencePolicies) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.ReferencePolicyList, err error) { +// List takes label and field selectors, and returns the list of ReferenceGrants that match those selectors. +func (c *referenceGrants) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.ReferenceGrantList, err error) { var timeout time.Duration if opts.TimeoutSeconds != nil { timeout = time.Duration(*opts.TimeoutSeconds) * time.Second } - result = &v1alpha2.ReferencePolicyList{} + result = &v1alpha2.ReferenceGrantList{} err = c.client.Get(). Namespace(c.ns). - Resource("referencepolicies"). + Resource("referencegrants"). VersionedParams(&opts, scheme.ParameterCodec). Timeout(timeout). Do(ctx). @@ -93,8 +93,8 @@ func (c *referencePolicies) List(ctx context.Context, opts v1.ListOptions) (resu return } -// Watch returns a watch.Interface that watches the requested referencePolicies. -func (c *referencePolicies) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { +// Watch returns a watch.Interface that watches the requested referenceGrants. +func (c *referenceGrants) 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 @@ -102,44 +102,44 @@ func (c *referencePolicies) Watch(ctx context.Context, opts v1.ListOptions) (wat opts.Watch = true return c.client.Get(). Namespace(c.ns). - Resource("referencepolicies"). + Resource("referencegrants"). VersionedParams(&opts, scheme.ParameterCodec). Timeout(timeout). Watch(ctx) } -// Create takes the representation of a referencePolicy and creates it. Returns the server's representation of the referencePolicy, and an error, if there is any. -func (c *referencePolicies) Create(ctx context.Context, referencePolicy *v1alpha2.ReferencePolicy, opts v1.CreateOptions) (result *v1alpha2.ReferencePolicy, err error) { - result = &v1alpha2.ReferencePolicy{} +// Create takes the representation of a referenceGrant and creates it. Returns the server's representation of the referenceGrant, and an error, if there is any. +func (c *referenceGrants) Create(ctx context.Context, referenceGrant *v1alpha2.ReferenceGrant, opts v1.CreateOptions) (result *v1alpha2.ReferenceGrant, err error) { + result = &v1alpha2.ReferenceGrant{} err = c.client.Post(). Namespace(c.ns). - Resource("referencepolicies"). + Resource("referencegrants"). VersionedParams(&opts, scheme.ParameterCodec). - Body(referencePolicy). + Body(referenceGrant). Do(ctx). Into(result) return } -// Update takes the representation of a referencePolicy and updates it. Returns the server's representation of the referencePolicy, and an error, if there is any. -func (c *referencePolicies) Update(ctx context.Context, referencePolicy *v1alpha2.ReferencePolicy, opts v1.UpdateOptions) (result *v1alpha2.ReferencePolicy, err error) { - result = &v1alpha2.ReferencePolicy{} +// Update takes the representation of a referenceGrant and updates it. Returns the server's representation of the referenceGrant, and an error, if there is any. +func (c *referenceGrants) Update(ctx context.Context, referenceGrant *v1alpha2.ReferenceGrant, opts v1.UpdateOptions) (result *v1alpha2.ReferenceGrant, err error) { + result = &v1alpha2.ReferenceGrant{} err = c.client.Put(). Namespace(c.ns). - Resource("referencepolicies"). - Name(referencePolicy.Name). + Resource("referencegrants"). + Name(referenceGrant.Name). VersionedParams(&opts, scheme.ParameterCodec). - Body(referencePolicy). + Body(referenceGrant). Do(ctx). Into(result) return } -// Delete takes name of the referencePolicy and deletes it. Returns an error if one occurs. -func (c *referencePolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { +// Delete takes name of the referenceGrant and deletes it. Returns an error if one occurs. +func (c *referenceGrants) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { return c.client.Delete(). Namespace(c.ns). - Resource("referencepolicies"). + Resource("referencegrants"). Name(name). Body(&opts). Do(ctx). @@ -147,14 +147,14 @@ func (c *referencePolicies) Delete(ctx context.Context, name string, opts v1.Del } // DeleteCollection deletes a collection of objects. -func (c *referencePolicies) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { +func (c *referenceGrants) 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("referencepolicies"). + Resource("referencegrants"). VersionedParams(&listOpts, scheme.ParameterCodec). Timeout(timeout). Body(&opts). @@ -162,12 +162,12 @@ func (c *referencePolicies) DeleteCollection(ctx context.Context, opts v1.Delete Error() } -// Patch applies the patch and returns the patched referencePolicy. -func (c *referencePolicies) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.ReferencePolicy, err error) { - result = &v1alpha2.ReferencePolicy{} +// Patch applies the patch and returns the patched referenceGrant. +func (c *referenceGrants) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.ReferenceGrant, err error) { + result = &v1alpha2.ReferenceGrant{} err = c.client.Patch(pt). Namespace(c.ns). - Resource("referencepolicies"). + Resource("referencegrants"). Name(name). SubResource(subresources...). VersionedParams(&opts, scheme.ParameterCodec). diff --git a/pkg/client/informers/externalversions/apis/v1alpha2/interface.go b/pkg/client/informers/externalversions/apis/v1alpha2/interface.go index 76943afe23..6f7f716d52 100644 --- a/pkg/client/informers/externalversions/apis/v1alpha2/interface.go +++ b/pkg/client/informers/externalversions/apis/v1alpha2/interface.go @@ -30,8 +30,8 @@ type Interface interface { GatewayClasses() GatewayClassInformer // HTTPRoutes returns a HTTPRouteInformer. HTTPRoutes() HTTPRouteInformer - // ReferencePolicies returns a ReferencePolicyInformer. - ReferencePolicies() ReferencePolicyInformer + // ReferenceGrants returns a ReferenceGrantInformer. + ReferenceGrants() ReferenceGrantInformer // TCPRoutes returns a TCPRouteInformer. TCPRoutes() TCPRouteInformer // TLSRoutes returns a TLSRouteInformer. @@ -66,9 +66,9 @@ func (v *version) HTTPRoutes() HTTPRouteInformer { return &hTTPRouteInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } -// ReferencePolicies returns a ReferencePolicyInformer. -func (v *version) ReferencePolicies() ReferencePolicyInformer { - return &referencePolicyInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +// ReferenceGrants returns a ReferenceGrantInformer. +func (v *version) ReferenceGrants() ReferenceGrantInformer { + return &referenceGrantInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } // TCPRoutes returns a TCPRouteInformer. diff --git a/pkg/client/informers/externalversions/apis/v1alpha2/referencepolicy.go b/pkg/client/informers/externalversions/apis/v1alpha2/referencegrant.go similarity index 55% rename from pkg/client/informers/externalversions/apis/v1alpha2/referencepolicy.go rename to pkg/client/informers/externalversions/apis/v1alpha2/referencegrant.go index 08e1551d2d..d7a91c434c 100644 --- a/pkg/client/informers/externalversions/apis/v1alpha2/referencepolicy.go +++ b/pkg/client/informers/externalversions/apis/v1alpha2/referencegrant.go @@ -32,59 +32,59 @@ import ( v1alpha2 "sigs.k8s.io/gateway-api/pkg/client/listers/apis/v1alpha2" ) -// ReferencePolicyInformer provides access to a shared informer and lister for -// ReferencePolicies. -type ReferencePolicyInformer interface { +// ReferenceGrantInformer provides access to a shared informer and lister for +// ReferenceGrants. +type ReferenceGrantInformer interface { Informer() cache.SharedIndexInformer - Lister() v1alpha2.ReferencePolicyLister + Lister() v1alpha2.ReferenceGrantLister } -type referencePolicyInformer struct { +type referenceGrantInformer struct { factory internalinterfaces.SharedInformerFactory tweakListOptions internalinterfaces.TweakListOptionsFunc namespace string } -// NewReferencePolicyInformer constructs a new informer for ReferencePolicy type. +// NewReferenceGrantInformer constructs a new informer for ReferenceGrant 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 NewReferencePolicyInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredReferencePolicyInformer(client, namespace, resyncPeriod, indexers, nil) +func NewReferenceGrantInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredReferenceGrantInformer(client, namespace, resyncPeriod, indexers, nil) } -// NewFilteredReferencePolicyInformer constructs a new informer for ReferencePolicy type. +// NewFilteredReferenceGrantInformer constructs a new informer for ReferenceGrant 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 NewFilteredReferencePolicyInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { +func NewFilteredReferenceGrantInformer(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().ReferencePolicies(namespace).List(context.TODO(), options) + return client.GatewayV1alpha2().ReferenceGrants(namespace).List(context.TODO(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha2().ReferencePolicies(namespace).Watch(context.TODO(), options) + return client.GatewayV1alpha2().ReferenceGrants(namespace).Watch(context.TODO(), options) }, }, - &apisv1alpha2.ReferencePolicy{}, + &apisv1alpha2.ReferenceGrant{}, resyncPeriod, indexers, ) } -func (f *referencePolicyInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredReferencePolicyInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +func (f *referenceGrantInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredReferenceGrantInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } -func (f *referencePolicyInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&apisv1alpha2.ReferencePolicy{}, f.defaultInformer) +func (f *referenceGrantInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apisv1alpha2.ReferenceGrant{}, f.defaultInformer) } -func (f *referencePolicyInformer) Lister() v1alpha2.ReferencePolicyLister { - return v1alpha2.NewReferencePolicyLister(f.Informer().GetIndexer()) +func (f *referenceGrantInformer) Lister() v1alpha2.ReferenceGrantLister { + return v1alpha2.NewReferenceGrantLister(f.Informer().GetIndexer()) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index 9caba89b7a..6f17f4f85f 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -59,8 +59,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1alpha2().GatewayClasses().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("httproutes"): return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1alpha2().HTTPRoutes().Informer()}, nil - case v1alpha2.SchemeGroupVersion.WithResource("referencepolicies"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1alpha2().ReferencePolicies().Informer()}, nil + case v1alpha2.SchemeGroupVersion.WithResource("referencegrants"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1alpha2().ReferenceGrants().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("tcproutes"): return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1alpha2().TCPRoutes().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("tlsroutes"): diff --git a/pkg/client/listers/apis/v1alpha2/expansion_generated.go b/pkg/client/listers/apis/v1alpha2/expansion_generated.go index 1e8f44a0af..7d3d39e47b 100644 --- a/pkg/client/listers/apis/v1alpha2/expansion_generated.go +++ b/pkg/client/listers/apis/v1alpha2/expansion_generated.go @@ -38,13 +38,13 @@ type HTTPRouteListerExpansion interface{} // HTTPRouteNamespaceLister. type HTTPRouteNamespaceListerExpansion interface{} -// ReferencePolicyListerExpansion allows custom methods to be added to -// ReferencePolicyLister. -type ReferencePolicyListerExpansion interface{} +// ReferenceGrantListerExpansion allows custom methods to be added to +// ReferenceGrantLister. +type ReferenceGrantListerExpansion interface{} -// ReferencePolicyNamespaceListerExpansion allows custom methods to be added to -// ReferencePolicyNamespaceLister. -type ReferencePolicyNamespaceListerExpansion interface{} +// ReferenceGrantNamespaceListerExpansion allows custom methods to be added to +// ReferenceGrantNamespaceLister. +type ReferenceGrantNamespaceListerExpansion interface{} // TCPRouteListerExpansion allows custom methods to be added to // TCPRouteLister. diff --git a/pkg/client/listers/apis/v1alpha2/referencegrant.go b/pkg/client/listers/apis/v1alpha2/referencegrant.go new file mode 100644 index 0000000000..eb8c7a5615 --- /dev/null +++ b/pkg/client/listers/apis/v1alpha2/referencegrant.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" +) + +// ReferenceGrantLister helps list ReferenceGrants. +// All objects returned here must be treated as read-only. +type ReferenceGrantLister interface { + // List lists all ReferenceGrants in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha2.ReferenceGrant, err error) + // ReferenceGrants returns an object that can list and get ReferenceGrants. + ReferenceGrants(namespace string) ReferenceGrantNamespaceLister + ReferenceGrantListerExpansion +} + +// referenceGrantLister implements the ReferenceGrantLister interface. +type referenceGrantLister struct { + indexer cache.Indexer +} + +// NewReferenceGrantLister returns a new ReferenceGrantLister. +func NewReferenceGrantLister(indexer cache.Indexer) ReferenceGrantLister { + return &referenceGrantLister{indexer: indexer} +} + +// List lists all ReferenceGrants in the indexer. +func (s *referenceGrantLister) List(selector labels.Selector) (ret []*v1alpha2.ReferenceGrant, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.ReferenceGrant)) + }) + return ret, err +} + +// ReferenceGrants returns an object that can list and get ReferenceGrants. +func (s *referenceGrantLister) ReferenceGrants(namespace string) ReferenceGrantNamespaceLister { + return referenceGrantNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ReferenceGrantNamespaceLister helps list and get ReferenceGrants. +// All objects returned here must be treated as read-only. +type ReferenceGrantNamespaceLister interface { + // List lists all ReferenceGrants in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha2.ReferenceGrant, err error) + // Get retrieves the ReferenceGrant from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha2.ReferenceGrant, error) + ReferenceGrantNamespaceListerExpansion +} + +// referenceGrantNamespaceLister implements the ReferenceGrantNamespaceLister +// interface. +type referenceGrantNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ReferenceGrants in the indexer for a given namespace. +func (s referenceGrantNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.ReferenceGrant, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.ReferenceGrant)) + }) + return ret, err +} + +// Get retrieves the ReferenceGrant from the indexer for a given namespace and name. +func (s referenceGrantNamespaceLister) Get(name string) (*v1alpha2.ReferenceGrant, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha2.Resource("referencegrant"), name) + } + return obj.(*v1alpha2.ReferenceGrant), nil +} diff --git a/pkg/client/listers/apis/v1alpha2/referencepolicy.go b/pkg/client/listers/apis/v1alpha2/referencepolicy.go deleted file mode 100644 index 5a1f994b9d..0000000000 --- a/pkg/client/listers/apis/v1alpha2/referencepolicy.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -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" -) - -// ReferencePolicyLister helps list ReferencePolicies. -// All objects returned here must be treated as read-only. -type ReferencePolicyLister interface { - // List lists all ReferencePolicies in the indexer. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha2.ReferencePolicy, err error) - // ReferencePolicies returns an object that can list and get ReferencePolicies. - ReferencePolicies(namespace string) ReferencePolicyNamespaceLister - ReferencePolicyListerExpansion -} - -// referencePolicyLister implements the ReferencePolicyLister interface. -type referencePolicyLister struct { - indexer cache.Indexer -} - -// NewReferencePolicyLister returns a new ReferencePolicyLister. -func NewReferencePolicyLister(indexer cache.Indexer) ReferencePolicyLister { - return &referencePolicyLister{indexer: indexer} -} - -// List lists all ReferencePolicies in the indexer. -func (s *referencePolicyLister) List(selector labels.Selector) (ret []*v1alpha2.ReferencePolicy, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha2.ReferencePolicy)) - }) - return ret, err -} - -// ReferencePolicies returns an object that can list and get ReferencePolicies. -func (s *referencePolicyLister) ReferencePolicies(namespace string) ReferencePolicyNamespaceLister { - return referencePolicyNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// ReferencePolicyNamespaceLister helps list and get ReferencePolicies. -// All objects returned here must be treated as read-only. -type ReferencePolicyNamespaceLister interface { - // List lists all ReferencePolicies in the indexer for a given namespace. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha2.ReferencePolicy, err error) - // Get retrieves the ReferencePolicy from the indexer for a given namespace and name. - // Objects returned here must be treated as read-only. - Get(name string) (*v1alpha2.ReferencePolicy, error) - ReferencePolicyNamespaceListerExpansion -} - -// referencePolicyNamespaceLister implements the ReferencePolicyNamespaceLister -// interface. -type referencePolicyNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all ReferencePolicies in the indexer for a given namespace. -func (s referencePolicyNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.ReferencePolicy, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha2.ReferencePolicy)) - }) - return ret, err -} - -// Get retrieves the ReferencePolicy from the indexer for a given namespace and name. -func (s referencePolicyNamespaceLister) Get(name string) (*v1alpha2.ReferencePolicy, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha2.Resource("referencepolicy"), name) - } - return obj.(*v1alpha2.ReferencePolicy), nil -} diff --git a/site-src/blog/2021/introducing-v1alpha2.md b/site-src/blog/2021/introducing-v1alpha2.md index 13bfe3597a..18245d6b90 100644 --- a/site-src/blog/2021/introducing-v1alpha2.md +++ b/site-src/blog/2021/introducing-v1alpha2.md @@ -53,20 +53,20 @@ Gateway API, we had several key feature requests that required this capability. Most notably, forwarding traffic to backends in other namespaces and referring to TLS certificates in other namespaces. -To accomplish this, we've introduced a new ReferencePolicy resource that +To accomplish this, we've introduced a new ReferenceGrant resource that provides a handshake mechanism. By default, references across namespaces are not permitted; creating a reference across a namespace (like a Route referencing a Service in another namespace) must be rejected by implementations. These -references can be accepted by creating a ReferencePolicy in the referent +references can be accepted by creating a ReferenceGrant in the referent (target) namespace, that specifies what Kind is allowed to accept incoming references, and from what namespace and Kind the references may be. -For example, the following ReferencePolicy would allow HTTPRoutes in the prod -namespace to forward traffic to Services wherever this ReferencePolicy was +For example, the following ReferenceGrant would allow HTTPRoutes in the prod +namespace to forward traffic to Services wherever this ReferenceGrant was installed: ```yaml -{% include 'v1alpha2/reference-policy.yaml' %} +{% include 'v1alpha2/reference-grant.yaml' %} ``` This is covered in more detail in [GEP 709](https://gateway-api.sigs.k8s.io/geps/gep-709/). diff --git a/site-src/concepts/api-overview.md b/site-src/concepts/api-overview.md index 96d34de3ae..5afead6ea7 100644 --- a/site-src/concepts/api-overview.md +++ b/site-src/concepts/api-overview.md @@ -18,9 +18,9 @@ section in the Security model for details. ## Resource model !!! note - As of v1alpha2, resources are in the `gateway.networking.k8s.io` API group as - Custom Resource Definitions (CRDs). Unqualified resource names below will implicitly - be in this API group. Prior to v1alpha1, the API group was `networking.x-k8s.io`. + Gateway API resources are in the `gateway.networking.k8s.io` API group as + Custom Resource Definitions (CRDs). Unqualified resource names below will + implicitly be in this API group. There are three main types of objects in our resource model: @@ -36,9 +36,9 @@ the cluster. GatewayClass defines a set of Gateways that share a common configuration and behaviour. Each GatewayClass will be handled by a single controller, although -controllers MAY handle more than one GatewayClass. +controllers may handle more than one GatewayClass. -GatewayClass is a cluster-scoped resource. There MUST be at least one +GatewayClass is a cluster-scoped resource. There must be at least one GatewayClass defined in order to be able to have functional Gateways. A controller that implements the Gateway API does so by providing an associated GatewayClass resource that the user can reference from their Gateway(s). @@ -62,8 +62,8 @@ have client traffic originating “outside” the cluster, this is not a requirement. It defines a request for a specific load balancer config that implements the -GatewayClass’ configuration and behaviour contract. The resource MAY be created -by an operator directly, or MAY be created by a controller handling a +GatewayClass’ configuration and behaviour contract. The resource may be created +by an operator directly, or may be created by a controller handling a GatewayClass. As the Gateway spec captures user intent, it may not contain a complete @@ -73,7 +73,7 @@ managing the GatewayClass to provide these settings for the user, resulting in a more portable spec. This behaviour will be made clear using the GatewayClass Status object. -A Gateway MAY be attached to one or more *Route references* which serve to direct +A Gateway may be attached to one or more *Route references* which serve to direct traffic for a subset of traffic *to a specific service.* ### Route Resources @@ -171,6 +171,31 @@ The following is required for a Route to be attached to a Gateway: 1. The Route needs an entry in its `parentRefs` field referencing the Gateway. 2. At least one listener on the Gateway needs to allow this attachment. +#### Referencing Gateways + +!!! info "Experimental Channel" + + The `Port` field described below is currently only included in the + "Experimental" channel of Gateway API. For more information on release + channels, refer to the [related documentation](https://gateway-api.sigs.k8s.io/concepts/versioning/#adding-experimental-fields). + +A Route can reference a Gateway by specifying the namespace (optional if the +Route and the Gateway are in the same namespace) and name of the Gateway in +a `parentRef`. A Route can further select a subset of listeners under the +Gateway using the following fields in `parentRef`: + +1. **SectionName** When `sectionName` is set, the Route selects the listener + with the specified name. +2. **Port** When `port` is set, the Route selects all listeners listening on + the specified port and with protocol compatible with this kind of Route. + +When multiple fields in `parentRef` are set, the Route selects listeners that +satisfy all conditions specified in those fields. For example, when both +`sectionName` and `port` are set, the Route selects listeners with the specified +name AND listening on the specified port. + +#### Restricting Route Attachment + Each Gateway listener can restrict which Routes can be attached with the following mechanisms: diff --git a/site-src/concepts/guidelines.md b/site-src/concepts/guidelines.md index 5adfed406a..ec51f810d8 100644 --- a/site-src/concepts/guidelines.md +++ b/site-src/concepts/guidelines.md @@ -2,6 +2,11 @@ There are some general design guidelines used throughout this API. +!!! note + Throughout the Gateway API documentation and specification, + keywords such as "MUST", "MAY", and "SHOULD" are used + broadly. These should be interpreted as described in RFC 2119. + ## Single resource consistency The Kubernetes API guarantees consistency only on a single resource level. There @@ -38,6 +43,44 @@ prescribed resolution, the following guiding principles should be applied: should be given to the resource appearing first in alphabetical order (namespace/name). For example, foo/bar would be given precedence over foo/baz. +## Gracefully Handling Future API Versions + +An important consideration when implementing this API is how it might change in +the future. Similar to the Ingress API before it, this API is designed to be +implemented by a variety of different products within the same cluster. That +means that the API version your implementation was developed with may be +different than the API version it is used with. At a minimum, the following +requirements must be met to ensure future versions of the API do not break your +implementation: + +* Handle fields with loosened validation without crashing +* Handle fields that have transitioned from required to optional without + crashing + +## Limitations of CRD and Webhook Validation + +CRD and webhook validation is not the final validation i.e. webhook is "nice UX" +but not schema enforcement. This validation is intended to provide immediate +feedback to users when they provide an invalid configuration. Write code +defensively with the assumption that at least some invalid input (Gateway API +resources) will reach your controller. Both Webhook and CRD validation is not +fully reliable because it: + +* May not be deployed correctly. +* May be loosened in future API releases. (Fields may contain values with less + restrictive validation in newer versions of the API). + +*Note: These limitations are not unique to Gateway API and apply more broadly to +any Kubernetes CRDs and webhooks.* + +Implementers should ensure that, even if unexpected values are encountered in +the API, their implementations are still as secure as possible and handle this +input gracefully. The most common response would be to reject the configuration +as malformed and signal the user via a condition in the status block. To avoid +duplicating work, Gateway API maintainers are considering adding a shared +validation package that implementations can use for this purpose. This is +tracked by [#926](https://github.com/kubernetes-sigs/gateway-api/issues/926). + ## Conformance As this API aims to cover a wide set of implementations and use cases, @@ -118,6 +161,7 @@ The "implementation-specific" designation allows a CORE or EXTENDED feature to be well-defined taking into account the realities of some features that are mostly but not entirely portable. + ## Kind vs. Resource Similar to other Kubernetes APIs, Gateway API uses "Kind" instead of "Resource" diff --git a/site-src/concepts/security-model.md b/site-src/concepts/security-model.md index aefba84a0c..b2fd7f674e 100644 --- a/site-src/concepts/security-model.md +++ b/site-src/concepts/security-model.md @@ -106,23 +106,23 @@ guarantee. If you used a custom label such as `env`, anyone that is able to label namespaces within your cluster would effectively be able to change the set of namespaces your Gateway supported. -### 2. ReferencePolicy +### 2. ReferenceGrant There are some cases where we allow other object references to cross namespace boundaries. This includes Gateways referencing Secrets and Routes referencing Backends (usually Services). In these cases, the required handshake is -accomplished with a ReferencePolicy resource. This resource exists within a +accomplished with a ReferenceGrant resource. This resource exists within a target namespace and can be used to allow references from other namespaces. -For example, the following ReferencePolicy allows references from Gateways in +For example, the following ReferenceGrant allows references from Gateways in the "prod" namespace to HTTPRoutes that are deployed in the same namespace as -the ReferencePolicy. +the ReferenceGrant. ```yaml -{% include 'v1alpha2/reference-policy.yaml' %} +{% include 'v1alpha2/reference-grant.yaml' %} ``` -For more information on ReferencePolicy, refer to our [detailed documentation -for this resource](/v1alpha2/api-types/referencepolicy.md). +For more information on ReferenceGrant, refer to our [detailed documentation +for this resource](/v1alpha2/api-types/referencegrant.md). ## Advanced Concept: Limiting Namespaces Where a GatewayClass Can Be Used Some infrastructure providers or cluster operators may wish to limit the diff --git a/site-src/concepts/versioning.md b/site-src/concepts/versioning.md index d5d0c1ff65..ba48e905c5 100644 --- a/site-src/concepts/versioning.md +++ b/site-src/concepts/versioning.md @@ -1,112 +1,62 @@ # Versioning -## Summary -Each Gateway API release is represented by a bundle version that represents -that specific combination of CRDs, API versions, and validating webhook. To -enable experimental fields, future releases of the API will include stable and -experimental CRD tracks. Users will be able to access experimental features by -installing the experimental CRDs. A cluster can contain either an experimental -or stable CRD for any resource at a given time. - -## Version Terminology -Gateway API has two related but different versioning schemes: - -### 1. API Versions (ex: v1alpha2) -Each API version provides a unique way to interact with the API. Significant -changes such as removing or renaming fields will be represented here. - -### 2. Bundle Versions (ex: v0.4.0) -Bundle versions are broader in scope. They use semantic versioning and include -the following: - -* API Types/CRDs +## Overview +Each new release of Gateway API is defined with a "bundle version" that +represents the Git tag of a release, such as v0.4.0. This contains the +following: + +* API Types (Go bindings for the resources) +* CRDs (Kubernetes definitions of the resources) * Validating Webhook -Each bundle may include multiple API versions, potentially introducing new ones -and/or removing old ones as part of a new bundle. - -## Limitations of Webhook and CRD Validation -CRD and webhook validation is not the final validation i.e. webhook is “nice UX” -but not schema enforcement. This validation is intended to provide immediate -feedback to users when they provide an invalid configuration, but can not -completely be relied on because it: - -* Is not guaranteed to be present or up to date in all clusters. -* Will likely never be sufficient to cover all edge cases. -* May be loosened in future API releases. - -## Persona Requirements -When implementing or using Gateway API, each persona has a unique set of -responsibilities to ensure we're providing a consistent experience. - -### API Authors: -* MUST provide conversion between API versions (excluding experimental fields), - starting with v1alpha2. -* MAY include the following changes to an existing API version with a new bundle - **patch** version: - * Clarifications to godocs - * Updates to CRDs and/or code to fix a bug - * Fixes to typos -* MAY include the following changes to an existing API version with a new bundle - **minor** version: - * Everything that is valid in a patch release - * New experimental API fields or resources - * Loosened validation - * Making required fields optional - * Removal of experimental fields - * Removal of experimental resources - * Graduation of fields or resources from experimental to stable track -* MAY introduce a new **API version** with a new bundle minor version, which may - include: - * Everything that is valid in a minor release - * Renamed fields - * Anything else that is valid in a new Kubernetes API version - * Removal/tombstoning of beta fields -* MAY release a new major bundle version (v1.0) as part of graduating the API to - GA and releasing a new API version. - -Note that each new bundle version, no matter how small, may include updated -CRDs, webhook, or both. Implementations may read annotations on Gateway API CRDs -(defined below) to determine the version and channel of CRDs that have been -installed in the cluster. - -### Implementers: -* MUST handle fields with loosened validation without crashing -* MUST handle fields that have transitioned from required to optional without - crashing -* MUST NOT rely on webhook or CRD validation as a security mechanism. If field - values need to be escaped to secure an implementation, both webhook and CRD - validation can be bypassed and cannot be relied on. Instead, implementations - should implement their own escaping or validation as necessary. To avoid - duplicating work, Gateway API maintainers are considering adding a shared - validation package that implementations can use for this purpose. This is - tracked by [#926](https://github.com/kubernetes-sigs/gateway-api/issues/926). - -### Installers: -* MUST install a full Gateway API bundle, with matching CRD and webhook - versions. - -## Adding Experimental Fields -Over time, it will be useful to add experimental fields to the API. In upstream -Kubernetes, those would generally be guarded with feature gates. With Gateway -API we will accomplish by releasing experimental versions of our CRDs. - -With this approach, we achieve a similar result. Instead of using feature gates -and validation to prevent fields from being set, we just release separate CRDs. -Once the API reaches beta, each bundle release can include 2 sets of CRDs, -stable and experimental. - -New fields will be added to the experimental set of CRDs first, and may graduate -to stable APIs later. Experimental fields will be marked with the -`+experimental` annotation in Go type definitions. Gateway API CRD generation -will exclude these fields from stable CRDs. Experimental fields may be removed -from the API. Due to the experimental nature of these CRDs, they are not -recommended for production use. - -If experimental fields are removed or renamed, the original field name should be -removed from the go struct, with a tombstone comment ensuring the field name -will not be reused. +### API Versions (e.g. v1alpha2, v1beta1) +Within Gateway API, API versions are primarily used to indicate the stability of +a resource. For example, if a resource has not yet graduated to beta, it is +still possible that it could either be removed from the API or changed in +backwards incompatible ways. For more information on API versions, refer to the +[full Kubernetes API versioning +documentation](https://kubernetes.io/docs/reference/using-api/#api-versioning). + +![Lifecycle of New Gateway API Resources](/images/lifecycle-new-resources.png) + + +### Release Channels (e.g. Experimental, Stable) +Gateway API provides 2 release channels: an Experimental one and a Stable one. + +The Stable release channel includes: + +* Resources that have graduated to beta +* All fields that have graduated to stable and are no longer considered + experimental + +The Experimental release channel includes everything in the Stable release +channel, plus: +* Alpha API resources +* New fields that are considered experimental and have not yet graduated to the + stable channel + +![Release Channel Overlap](/images/release-channel-overlap.png) + + +Release channels are used to indicate feature stability within Gateway API. For +example, even if a resource has already graduated to beta, we need a way to test +out new fields and features before committing to their long term stability. With +upstream Kubernetes APIs, this is accomplished with [feature +gates](https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/). +Unfortunately, CRDs do not have a similar concept yet. + +Instead of trying to recreate feature gates in this project, we've introduced +release channels. Starting in v0.5.0, all new fields and features will start in +the Experimental release channel. From that point, these may graduate to the +Stable release channel or be dropped from the API entirely. See +[GEP-922](/geps/gep-922) for a more detailed discussion of this approach to new +fields and features. + +![Lifecycle of New Gateway API Fields](/images/lifecycle-new-fields.png) + + +## Version Indicators Each CRD will be published with annotations that indicate their bundle version and channel: @@ -114,3 +64,83 @@ and channel: gateway.networking.k8s.io/bundle-version: v0.4.0 gateway.networking.k8s.io/channel: stable|experimental ``` + +## What can Change +When using or implementing this API, it is important to understand what can +change across API versions. + +### Patch version (e.g. v0.4.0 -> v0.4.1) +* Clarifications to godocs +* Updates to CRDs and/or code to fix a bug +* Fixes to typos + +### Minor version (e.g. v0.4.0 -> v0.5.0) +* Everything that is valid in a patch release +* New experimental API fields or resources +* Loosened validation +* Making required fields optional +* Removal of experimental fields +* Removal of experimental resources +* Graduation of fields or resources from experimental to stable track +* Introduction of a new **API version**, which may also include: + * Renamed fields + * Anything else that is valid in a new Kubernetes API version + * Removal/tombstoning of beta fields +* Removal of an API resource following [Kubernetes deprecation + policy](https://kubernetes.io/docs/reference/using-api/deprecation-policy/) + +### Major version (e.g. v0.x to v1.0) +* There are no API compatibility guarantees when the major version changes. + +## Graduation Criteria + +### Resources + +#### Alpha -> Beta +A resource to graduate from alpha to beta must meet the following criteria: + +* Implemented by several implementations. +* Conformance test framework is in place, with some coverage of basic + functionality. +* Validation is well thought out. +* Most of the API surface is being exercised by users. +* Approval from subproject owners + KEP reviewers. + +#### Beta -> GA + +A resource to graduate from beta to GA must meet the following criteria: + +* Almost all of the fields and behavior have conformance test coverage. +* Multiple conformant implementations. +* Widespread implementation and usage. +* At least 6 months of soak time as a beta API. +* Approval from subproject owners + KEP reviewers. + +### Fields + +#### Experimental -> Stable +As described above, field level stability is layered on top of beta and GA +resources (no fields in alpha resources can be considered stable). The +requirements for a field to graduate from experimental to stable depend on the +API version of the resource it is a part of. For a field to be considered +stable, it needs to meet the same criteria of the resource it is contained in. + +If a resource has graduated to beta, an experimental field must meet all of the +beta graduation criteria before graduating to stable. Similarly, if a resource +has graduated to GA, a field must meet all of the beta and GA graduation +criteria. There is one slight variation here, instead of 6 months of soak time +as a beta API, a field graduating to stable requires 6 months of soak time as an +experimental field. + +## Out of Scope +### Unreleased APIs +This project will have frequent updates to the master branch. There are no +compatibility guarantees associated with code in any branch, including master, +until it has been released. For example, changes may be reverted before a +release is published. For the best results, use the latest published release of +this project. + +### Source Code +We do not provide stability guarantees for source code imports. The Interfaces +and behavior may change in an unexpected and backwards-incompatible way in any +future release. diff --git a/site-src/faq.md b/site-src/faq.md index 7667186370..286758e875 100644 --- a/site-src/faq.md +++ b/site-src/faq.md @@ -54,12 +54,10 @@ A: Gateway API releases are tags of the [Github repository][1]. The [Github releases][2] page shows all the releases. -* **Q: How should I think about the alpha release?
** - A: The `v1alpha1` release will be the first Gateway API release. As - various projects begin implementing the API, and operators start using - it, the working group will collect feedback and issues, which will - guide what revisions are needed for the next release. It is possible - that the next release will contain breaking changes. +* **Q: How should I think about alpha API versions?
** + A: Similar to upstream Kubernetes, alpha API versions indicate that resources + are still experimental in nature and may either be removed or changed in + breaking ways in future releases of Gateway API. * **Q: Which Kubernetes versions are supported?
** A: Generally, we support Kubernetes 1.16+, but certain features like diff --git a/site-src/geps/gep-1016.md b/site-src/geps/gep-1016.md new file mode 100644 index 0000000000..2b537009e4 --- /dev/null +++ b/site-src/geps/gep-1016.md @@ -0,0 +1,707 @@ +# GEP-1016: GRPCRoute + +* Issue: [#1016](https://github.com/kubernetes-sigs/gateway-api/issues/1016) +* Status: Implementable + +(See definitions in [Kubernetes KEP][kep-status]). + +[kep-status]: https://github.com/kubernetes/enhancements/blob/master/keps/NNNN-kep-template/kep.yaml#L9 + +## Goal + +Add an idiomatic GRPCRoute for routing gRPC traffic. + +## Non-Goals + +While certain gRPC implementations support multiple transports and multiple +interface definition languages (IDLs), this proposal limits itself to +[HTTP/2](https://developers.google.com/web/fundamentals/performance/http2) as +the transport and [Protocol Buffers](https://developers.google.com/protocol-buffers) +as the IDL, which makes up the vast majority of gRPC traffic in the wild. + +## Introduction + +While it would be possible to support gRPC via custom, out-of-tree CRDs, in the long run, this would +lead to a fragmented ecosystem. + +gRPC is a [popular RPC framework adopted widely across the industry](https://grpc.io/about/#whos-using-grpc-and-why). +The protocol is used pervasively within the Kubernetes project itself as the basis for +many interfaces, including: + +- [the CSI](https://github.com/container-storage-interface/spec/blob/5b0d4540158a260cb3347ef1c87ede8600afb9bf/spec.md), +- [the CRI](https://github.com/kubernetes/cri-api/blob/49fe8b135f4556ea603b1b49470f8365b62f808e/README.md), +- [the device plugin framework](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/) + +Given gRPC's importance in the application-layer networking space and to +the Kubernetes project in particular, we must ensure that the gRPC control plane +configuration landscape does not Balkanize. + +### Encapsulated Network Protocols + +It is theoretically possible to route gRPC traffic using only `HTTPRoute` +resources, but there are several serious problems with forcing gRPC users to route traffic at +the level of HTTP. This is why we propose a new resource. + +In setting this precendent, we must also introduce a coherent policy for _when_ +to introduce a custom `Route` resource for an encapsulated protocol for which a +lower layer protocol already exists. We propose the following criteria for such +an addition. + +- Users of the encapsulated protocol would miss out on significant conventional features from their ecosystem if forced to route at a lower layer. +- Users of the enapsulated protocol would experience a degraded user experience if forced to route at a lower layer. +- The encapsulated protocol has a significant user base, particularly in the Kubernetes community. + +gRPC meets _all_ of these criteria and is therefore, we contend, a strong +candidate for inclusion in the Gateway APIs. + +#### HTTP/2 Cleartext + +gRPC allows HTTP/2 cleartext communication (H2C). This is conventionally deployed for +testing. Many control plane implementations do not support this by default and +would require special configuration to work properly. + +#### Content-Based Routing + +While not included in the scope of this initial GEP, a common use case cited for +routing gRPC is payload-aware routing. That is, routing rules which determine a +backend based on the contents of the protocol buffer payload. + +#### User Experience + +The user experience would also degrade significantly if forced to route at the level of HTTP. + +- Encoding services and methods as URIs (an implementation detail of gRPC) +- The [Transfer Encoding header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding) for trailers +- Many features supported by HTTP/2 but not by gRPC, such as + - Query parameters + - Methods besides `POST` + - [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) + + +#### Proxyless Service Mesh + +The gRPC library supports proxyless service mesh, a system by which routing +configuration is received and acted upon not by an in-line proxy or sidecar +proxy but by the client itself. Eventually, `GRPCRoute` in the Gateway APIs +should support this feature. However, to date, there are no HTTP client +libraries capable of participating in a proxyless service mesh. + +--- + +### Cross Serving + +Occasionally, gRPC users will place gRPC services on the same hostname/port +combination as HTTP services. For example, `foo.com:443/v1` might serve +REST+JSON while `foo.com:443/com.foo.WidgetService/` serves gRPC. Such an +arrangement in the Gateway APIs poses complex technical challenges. How are +GRPCRoutes to be reconciled with HTTPRoutes? And how should invididual +implementations accomplisht this? + +After a long look at the implementations with which the author is familiar, it +was deemed technically infeasible. Furthermore, after surveying the gRPC +community, this was found to be a niche use case to begin with. + +In any case, users wishing to accomplish this always have the option of using +`HTTPRoute` resources to achieve this use case, at the cost of a degraded user +experience. + +If at some point in the future, demand for this use case increases and we have +reason to believe that the feasibility of implementation has improved, this +would be a backward compatible change. + +As such, implementations that support GRPCRoute must enforce uniqueness of +hostnames between `GRPCRoute`s and `HTTPRoute`s. 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. + + +## API + +The API deviates from `HTTPRoute` where it results in a better UX for gRPC +users, while mirroring it in all other cases. + +### Example `GRPCRoute` + +```yaml +kind: GRPCRoute +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: foo-grpcroute +spec: + parentRefs: + - name: my-gateway + hostnames: + - foo.com + - bar.com + rules: + - matches: + method: + service: helloworld.Greeter + method: SayHello + headers: + - type: Exact + name: magic + value: foo + + filters: + - type: RequestHeaderModifierFilter + add: + - name: my-header + value: foo + + - type: RequestMirrorPolicyFilter + destination: + backendRef: + name: mirror-svc + + backendRefs: + - name: foo-v1 + weight: 90 + - name: foo-v2 + weight: 10 +``` + +#### Method Matchers + +It's been pointed out that the `method` field above stutters. That is, in order +to specify a method matcher, one must type the string `method` twice in a row. +This is an artifact of less-than-clear nomenclature within gRPC. There +_are_ alternatives for the naming here, but none of them would actually be an +improvement on the stutter. Consider the following URI: + +`/foo.bar.v1.WidgetService/GetWidget` + +- `/foo.bar.v1.WidgetService/GetWidget` is called the method or, less commonly, the _full_ method. +- `foo.bar.v1.WidgetService` is called the service or, less commonly, the _full_ service (since `WidgetService` can reasonably be called the service)] +- `GetWidget` is called the method. + +These terms _could_ be added in, but these names are found almost exclusively +within the various gRPC implementations. And inconsistently across those +implementations. + +Therefore, we opt for the stutter over any of the longer names outlined above. + +#### Matcher Types + +`GRPCRoute` method matchers admits two types: `Exact` and `RegularExpression`. +If not specified, the match will be treated as type `Exact`. Method matchers +will act _as if_ a URI match had been used. A full matrix of equivalent behavior +is provided below: + +##### Type Exact + +|Service|Method|URI Matcher| +|----------|----------|-----------| +|Specified|Specified|Exact `/${SERVICE}/${METHOD}`| +|Specified|Unspecified|Prefix `/${SERVICE}/`| +|Unspecified|Specified|Suffix `/${METHOD}/` or Regex `/.+/${METHOD}`| +|Unspecified|Unspecified|Not allowed| + +##### Type RegularExpression + +|Service|Method|URI Matcher| +|----------|----------|-----------| +|Specified|Specified|Regex `/${SERVICE}/${METHOD}`| +|Specified|Unspecified|Regex `/${SERVICE}/.+`| +|Unspecified|Specified|Regex `/.+/${METHOD}`| +|Unspecified|Unspecified|Prefix `/`| + +##### Method specified but not Service + +In the table above, `Service` unspecified and `Method` specified with type Exact +is listed as being equivalent to a path matcher with type suffix or type regex. +We imagine that many GRPCRoute implementations will be done using translation to +`HTTPRoute`s. `HTTPRoute` does not support a Suffix matcher and its Regex +matcher is specified as "Custom" support. In order to accommodate `GRPCRoute` +implementations built on top of `HTTPRoute` implementations without regex +support, we list this particular case as having custom support within the +context of `GRPCRoute`. + +#### Transport + +No new `ProtocolType` will be added. While gRPC _does_ have some special +HTTP usage (HTTP/2 cleartext and HTTP/2 without an upgrade from HTTP/1.1), +`GRPCRoute` will be used in conjunction with the existing `HTTP` and `HTTPS` +ProtocolTypes. + +Implementations supporting `GRPCRoute` with the `HTTPS` `ProtocolType` must +accept HTTP/2 connections without an [initial upgrade from HTTP/1.1](https://datatracker.ietf.org/doc/html/rfc7230#section-6.7). 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 connections without an [initial upgrade from HTTP/1.1](https://datatracker.ietf.org/doc/html/rfc7230#section-6.7). If the implementation does not support this, then it +should raise a "Detached" condition for the affected listener with a reason of +"UnsupportedProtocol" + + +### Structs + +{% raw%} +```go +// +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"` +} + +// 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. + // + // 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. + + // If unspecified or invalid (refers to a non-existent resource or a Service + // with no endpoints), the rule performs no forwarding. If there are also no + // filters specified that would result in a response being sent, a gRPC `UNAVAILABLE` + // status is returned. `UNAVAILABLE` responses must be sent so that the overall + // weight is respected; if an invalid backend is requested to have 80% of + // requests, then 80% of requests must get a `UNAVAILABLE` instead. + // 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: +// +// ``` +// match: +// 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:"path,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"` +} + +// GRPCPathMatch 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:"value,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:"value,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 + +const ( + // Matches the service and/or method exactly and with case sensitivity. + PathMatchExact PathMatchType = "Exact" + + // Matches if the service and/or method matches the given regular expression with + // case sensitivity. + // + // Since `"RegularExpression"` has custom conformance, implementations + // can support POSIX, PCRE, RE2 or any other regular expression dialect. + // Please read the implementation's documentation to determine the supported + // dialect. + PathMatchRegularExpression PathMatchType = "RegularExpression" +) + +// 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:Enum=Exact;RegularExpression +type HeaderMatchType string + +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=256 +// +kubebuilder:validation:Pattern=`^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$` +type HeaderName string + +// 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 ReferenceGrant, the controller must ensure the + // "ResolvedRefs" condition on the Route is set to `status: False`, + // with the "RefNotPermitted" reason and not configure this backend in the + // underlying implementation. + // + // In either error case, the Message of the `ResolvedRefs` Condition + // should be used to provide more detail about the problem. + // + // Support: Custom + // + // +optional + BackendRef `json:",inline"` + + // Filters defined at this level should be executed if and only if the + // request is being forwarded to the backend defined here. + // + // Support: Custom (For broader support of filters, use the Filters field + // in GRPCRouteRule.) + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Filters []GRPCRouteFilter `json:"filters,omitempty"` +} + +// 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 + // + // 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 + // Support: Implementation-specific + // + // +optional + ExtensionRef *LocalObjectReference `json:"extensionRef,omitempty"` +} +``` +{% endraw%} + + + + +## Beta Graduation Criteria + +- `GRPCRoute` has been implemented by at least 2 controllers. +- Conformance tests are in place for the majority of the API surface. +- It is known that users of `GRPCRoute` exist. +- An API review has been performed by upstream Kubernetes reviewers. + +## GA Graduation Criteria + +- `GRPCRoute` has been implemented by at least 4 controllers. +- Exhaustive conformance tests are in place. +- Adoption of `GRPCRoute` has been shown to have expanded beyond its initial set of users. + +## Future Enhancements + +Many more ideas have been discussed for the `GRPCRoute` resource, but in the +interest of keeping this particular proposal tractable, they have been deferred +for future proposals. Enough thought has been given to these use cases at the +moment, however, that all of the following may be added at a later date in a +backward-compatible manner. + +Some of these ideas are: + +- Integration with Service Meshes (both sidecar-proxied and proxyless) +- Better UX for enabling reflection support +- gRPC Web support +- HTTP/JSON transcoding at the gateway +- Protobuf payload-based routing diff --git a/site-src/geps/gep-709.md b/site-src/geps/gep-709.md index 10f1094749..ff5f1fc8b2 100644 --- a/site-src/geps/gep-709.md +++ b/site-src/geps/gep-709.md @@ -3,12 +3,16 @@ * Issue: [#709](https://github.com/kubernetes-sigs/gateway-api/issues/709) * Status: Implemented +!!! note + This resource was originally named "ReferencePolicy". It was renamed + to "ReferenceGrant" to avoid any confusion with policy attachment. + ## TLDR This GEP attempts to enable cross namespace forwarding from Routes and provide a way to simplify adding Route inclusion (Routes including other Routes) in the future. These are closely related concepts that can be solved with a new -ReferencePolicy resource that enables app admins to describe where they trust +ReferenceGrant resource that enables app admins to describe where they trust references from. ## Motivation/User Journeys/Background @@ -22,7 +26,7 @@ capabilities for cross namespace references: 1. Mesh overrides to target Services in different namespaces. (For more info, see GEP [#713](https://github.com/kubernetes-sigs/gateway-api/issues/713)) -## ReferencePolicy +## ReferenceGrant Anytime we allow crossing a namespace boundary, we need to be very cautious. In the past, we've seen that forwarding traffic across namespace boundaries is @@ -32,17 +36,17 @@ emerge. To ensure that Gateway API is able to safely provide this functionality, we need to enforce a handshake mechanism that requires resources in both namespaces to -agree to this reference. To accomplish that, a new ReferencePolicy resource +agree to this reference. To accomplish that, a new ReferenceGrant resource should be introduced. -![Reference Policy](images/709-referencepolicy.png) +![Reference Policy](images/709-referencegrant.png) With this model, Routes would be able to directly reference Routes and Services in other namespaces. These references would only be considered valid if a -ReferencePolicy in the target namespace explicitly allowed it. +ReferenceGrant in the target namespace explicitly allowed it. The following example shows how a HTTPRoute in namespace foo could reference -a Service in namespace bar. In this example a ReferencePolicy in the bar +a Service in namespace bar. In this example a ReferenceGrant in the bar namespace explicitly allows references to Services from HTTPRoutes in the foo namespace. @@ -60,7 +64,7 @@ spec: - name: bar namespace: bar --- -kind: ReferencePolicy +kind: ReferenceGrant metadata: name: bar namespace: bar @@ -78,8 +82,8 @@ spec: This proposed API is fairly straightforward, but comes with a few notable decisions: -1. Each ReferencePolicy only supports a single From and To section. Additional - trust relationships can be modeled with additional ReferencePolicy resources. +1. Each ReferenceGrant only supports a single From and To section. Additional + trust relationships can be modeled with additional ReferenceGrant resources. 1. Resource names are intentionally excluded from this policy for simplicity and because they rarely provide any meaningful protection. A user that is able to write to resources of a certain kind within a namespace can always rename @@ -88,23 +92,23 @@ decisions: more powerful it may encourage unnecessarily insecure configuration. ```go -// ReferencePolicy identifies kinds of resources in other namespaces that are +// ReferenceGrant identifies kinds of resources in other namespaces that are // trusted to reference the specified kinds of resources in the local namespace. -// Each ReferencePolicy can be used to represent a unique trust relationship. +// Each ReferenceGrant can be used to represent a unique trust relationship. // Additional Reference Policies can be used to add to the set of trusted // sources of inbound references for the namespace they are defined within. -type ReferencePolicy struct { +type ReferenceGrant struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - // Spec defines the desired state of ReferencePolicy. - Spec ReferencePolicySpec `json:"spec,omitempty"` + // Spec defines the desired state of ReferenceGrant. + Spec ReferenceGrantSpec `json:"spec,omitempty"` } -// ReferencePolicySpec identifies a cross namespace relationship that is trusted +// ReferenceGrantSpec identifies a cross namespace relationship that is trusted // for Gateway API. -type ReferencePolicySpec struct { +type ReferenceGrantSpec struct { // From describes the trusted namespaces and kinds that can reference the // resources described in "To". Each entry in this list must be considered // to be an additional place that references can be valid from, or to put @@ -113,7 +117,7 @@ type ReferencePolicySpec struct { // Support: Core // // +kubebuilder:validation:MinItems=1 - From []ReferencePolicyFrom `json:"from"` + From []ReferenceGrantFrom `json:"from"` // To describes the resources that may be referenced by the resources // described in "From". Each entry in this list must be considered to be an @@ -123,11 +127,11 @@ type ReferencePolicySpec struct { // Support: Core // // +kubebuilder:validation:MinItems=1 - To []ReferencePolicyTo `json:"to"` + To []ReferenceGrantTo `json:"to"` } -// ReferencePolicyFrom describes trusted namespaces and kinds. -type ReferencePolicyFrom struct { +// ReferenceGrantFrom describes trusted namespaces and kinds. +type ReferenceGrantFrom struct { // Group is the group of the referrent. // // Support: Core @@ -158,9 +162,9 @@ type ReferencePolicyFrom struct { Namespace string `json:"namespace,omitempty"` } -// ReferencePolicyTo describes what Kinds are allowed as targets of the +// ReferenceGrantTo describes what Kinds are allowed as targets of the // references. -type ReferencePolicyTo struct { +type ReferenceGrantTo struct { // Group is the group of the referrent. // // Support: Core @@ -193,17 +197,17 @@ type ReferencePolicyTo struct { references. * Provides consistent way to control references to any resource from a Route. * Can be extended in the future for additional use cases. -* A single ReferencePolicy resource can be used for a namespace in place of +* A single ReferenceGrant resource can be used for a namespace in place of separate handshake config on each Service or Route resource. #### Exceptions -There are some situations where it MAY be acceptable to ignore ReferencePolicy +There are some situations where it MAY be acceptable to ignore ReferenceGrant in favor of some other security mechanism. This MAY only be done if other mechanisms like NetworkPolicy can effectively limit cross-namespace references by the implementation. An implementation choosing to make this exception MUST clearly document that -ReferencePolicy is not honored by their implementations and detail which +ReferenceGrant is not honored by their implementations and detail which alternative safeguards are available. Note that this is unlikely to apply to ingress implementations of the API and will not apply to all mesh implementations. @@ -211,7 +215,7 @@ implementations. For an example of the risks involved in cross-namespace references, refer to [CVE-2021-25740](https://github.com/kubernetes/kubernetes/issues/103675). Implementations of this API need to be very careful to avoid confused deputy -attacks. ReferencePolicy provides a safeguard for that. Exceptions MUST only +attacks. ReferenceGrant provides a safeguard for that. Exceptions MUST only be made by implementations that are absolutely certain that other equally effective safeguards are in place. @@ -239,7 +243,7 @@ type BackendRef struct { ## Alternatives ### Inline Config -Instead of ReferencePolicy, it is possible to represent these relationships +Instead of ReferenceGrant, it is possible to represent these relationships inline. ![Inline](images/709-inline.png) @@ -275,7 +279,7 @@ concept to all potential backend types. * Although closely related, this GEP does not attempt to improve the Gateway->Route relationship. That will instead be covered by a future GEP. -* Although this GEP explores how ReferencePolicy could enable Route inclusion, +* Although this GEP explores how ReferenceGrant could enable Route inclusion, the details of that feature will be left for a future GEP. ## References diff --git a/site-src/geps/gep-724.md b/site-src/geps/gep-724.md index 4b86369c92..5e2506c276 100644 --- a/site-src/geps/gep-724.md +++ b/site-src/geps/gep-724.md @@ -163,10 +163,10 @@ Of course we do still need a handshake that will enable cross-namespace references between Routes and Gateways. This proposal leaves in the core capabilities of the v1alpha1 API for this. Gateways can specify the namespaces they trust Routes to bind from, and Routes directly reference the Gateways they -want to attach to. This is largely similar to the ReferencePolicy model proposed +want to attach to. This is largely similar to the ReferenceGrant model proposed for Route->Service references, but is embedded within the Route and Gateway resources. The alternatives below explore what this could look like with -ReferencePolicy. +ReferenceGrant. ## API Changes @@ -524,7 +524,7 @@ struct would be replaced with the `ParentRef` struct included above. ### Disadvantages * Attaching a Route to a named listener with SectionName may be a bit confusing. -* Does not utilize existing ReferencePolicy mechanism. +* Does not utilize existing ReferenceGrant mechanism. * May be more difficult to understand which Routes are attached to a Gateway. * Adding/replacing a Gateway requires changes to Routes. @@ -535,15 +535,15 @@ complexity. ## Alternatives -### 1. ReferencePolicy with Gateways selecting Routes +### 1. ReferenceGrant with Gateways selecting Routes -![ReferencePolicy with Gateways selecting Routes](images/724-alt1.png) +![ReferenceGrant with Gateways selecting Routes](images/724-alt1.png) A compelling alternative to this proposal would involve retaining the Route selector in Gateway and replacing the trust concept in Routes with -ReferencePolicy. To represent the same example as above, we'd use a Route +ReferenceGrant. To represent the same example as above, we'd use a Route selector on Gateway, a corresponding label on the HTTPRoute, and a -ReferencePolicy that allowed it: +ReferenceGrant that allowed it: ```yaml kind: Gateway @@ -576,7 +576,7 @@ spec: matches: - path: /bar --- -kind: ReferencePolicy +kind: ReferenceGrant metadata: name: infra-gateways namespace: foo @@ -592,34 +592,34 @@ spec: #### Advantages -* Consistent use of ReferencePolicy throughout the API. +* Consistent use of ReferenceGrant throughout the API. * Provides a single way of binding Gateways to Routes. #### Disadvantages * Even the simplest cross-namespace reference from Gateway -> Route would - require a ReferencePolicy in each target namespace. + require a ReferenceGrant in each target namespace. * Existing demos and examples would become significantly more verbose. * Does not suppport attaching Routes to arbitrary parents. * Does not prevent accidental exposure of Routes. * Route owners have limited control in terms of which Gateways their Route is attached to. -### 2. ReferencePolicy with Routes referencing Gateways +### 2. ReferenceGrant with Routes referencing Gateways -![ReferencePolicy with Routes referencing Gateways](images/724-alt2.png) +![ReferenceGrant with Routes referencing Gateways](images/724-alt2.png) -The other way we could use ReferencePolicy would be with Routes referencing +The other way we could use ReferenceGrant would be with Routes referencing Gateways. Unfortunately the nested structure of Gateways makes this nearly impossible to do effectively. A core concept for Gateways is that each listener should be able to attach to an entirely different set of Routes. For example, a Gateway may want to delegate foo.com to the foo namespace and bar.com to the bar namespace. Unfortunately that would be very difficult to recreate with -ReferencePolicy. +ReferenceGrant. -ReferencePolicy is fundamentally about trusting references from resource of kind +ReferenceGrant is fundamentally about trusting references from resource of kind Foo in to resources of kind Bar. Names and section names are intentionally -excluded. If we added both of those concepts to ReferencePolicy, this would be +excluded. If we added both of those concepts to ReferenceGrant, this would be possible, but quite complex and verbose. This is what the example from above would look like with this approach: @@ -634,7 +634,7 @@ spec: hostname: foo.com port: 80 --- -kind: ReferencePolicy +kind: ReferenceGrant metadata: name: foo-lb namespace: infra @@ -667,7 +667,7 @@ spec: #### Advantages -* Consistent use of ReferencePolicy throughout the API. +* Consistent use of ReferenceGrant throughout the API. * Provides a single way of binding Gateways to Routes. * Supports attaching Routes to arbitrary parents. * Prevents accidental exposure of Routes. @@ -675,18 +675,18 @@ spec: #### Disadvantages * In most cases, each listener in a Gateway would require a unique - ReferencePolicy resource. + ReferenceGrant resource. * Even the simplest cross-namespace reference from Route -> Gateway would - require a ReferencePolicy in each target namespace. This could either rule + require a ReferenceGrant in each target namespace. This could either rule out or significantly complicate self-service use-cases. * Existing demos and examples would become significantly more verbose. -* ReferencePolicy would become more complex for all other use cases. +* ReferenceGrant would become more complex for all other use cases. ## References **GEPs** -* [GEP 709: ReferencePolicy + Cross Namespace References from Routes](/geps/gep-709) +* [GEP 709: ReferenceGrant + Cross Namespace References from Routes](/geps/gep-709) **Docs:** diff --git a/site-src/geps/gep-735.md b/site-src/geps/gep-735.md index 9291803756..63693fb7bc 100644 --- a/site-src/geps/gep-735.md +++ b/site-src/geps/gep-735.md @@ -1,7 +1,7 @@ # GEP-735: TCP and UDP addresses matching * Issue: [#735](https://github.com/kubernetes-sigs/gateway-api/issues/735) -* Status: Implemented +* Status: Provisional ## TLDR diff --git a/site-src/geps/gep-746.md b/site-src/geps/gep-746.md index 4cb41168d8..1a0c9798b0 100644 --- a/site-src/geps/gep-746.md +++ b/site-src/geps/gep-746.md @@ -65,7 +65,7 @@ tools like cert-manager that can watch Routes, generate certs for them, and attach them to a Gateway. #### 2. Cross Namespace Cert Direct References from Gateways -With the already established ReferencePolicy concept, we have established a safe +With the already established ReferenceGrant concept, we have established a safe way to reference resources across namespaces. Although this would require some coordination between Gateway and App owners, it would enable App owners to retain full control of the certs used by their app without the extra confusion @@ -95,7 +95,7 @@ one of the following safeguards: domain. 2. A way to configure which namespaces could attach certificates to each Gateway (or Listener). -3. A way to use ReferencePolicy to indicate where references from Secrets to +3. A way to use ReferenceGrant to indicate where references from Secrets to Gateways were trusted from and to. ## API @@ -105,7 +105,7 @@ The API changes proposed here are quite small, mostly removing fields. ### Changes 1. The `LocalObjectReference` used for the `CertificateRef` field in `GatewayTLSConfig` would be replaced with an `ObjectReference`. -1. `ReferencePolicy` would be updated to note that references from Gateways to +1. `ReferenceGrant` would be updated to note that references from Gateways to Secrets were part of the Core support level. ### Removals diff --git a/site-src/geps/gep-851.md b/site-src/geps/gep-851.md index dfe40ac639..7e5d474f16 100644 --- a/site-src/geps/gep-851.md +++ b/site-src/geps/gep-851.md @@ -54,8 +54,8 @@ following `CertificateRefs` field: // a Listener, but this behavior is implementation-specific. // // References to a resource in different namespace are invalid UNLESS there - // is a ReferencePolicy in the target namespace that allows the certificate - // to be attached. If a ReferencePolicy does not allow this reference, the + // is a ReferenceGrant in the target namespace that allows the certificate + // to be attached. If a ReferenceGrant does not allow this reference, the // "ResolvedRefs" condition MUST be set to False for this listener with the // "InvalidCertificateRef" reason. // diff --git a/site-src/geps/gep-917.md b/site-src/geps/gep-917.md index 2f04d8b8f0..aeb83d410e 100644 --- a/site-src/geps/gep-917.md +++ b/site-src/geps/gep-917.md @@ -88,7 +88,7 @@ All implementations must support all the Core functions on the following resourc - GatewayClass - Gateway -- ReferencePolicy +- ReferenceGrant The following resources are optional to support, but have defined behavior if you do: diff --git a/site-src/geps/images/709-referencepolicy.png b/site-src/geps/images/709-referencegrant.png similarity index 100% rename from site-src/geps/images/709-referencepolicy.png rename to site-src/geps/images/709-referencegrant.png diff --git a/site-src/images/lifecycle-new-fields.png b/site-src/images/lifecycle-new-fields.png new file mode 100644 index 0000000000..3d6361e7db Binary files /dev/null and b/site-src/images/lifecycle-new-fields.png differ diff --git a/site-src/images/lifecycle-new-resources.png b/site-src/images/lifecycle-new-resources.png new file mode 100644 index 0000000000..27f80bb24d Binary files /dev/null and b/site-src/images/lifecycle-new-resources.png differ diff --git a/site-src/images/release-channel-overlap.png b/site-src/images/release-channel-overlap.png new file mode 100644 index 0000000000..a6f410c65b Binary files /dev/null and b/site-src/images/release-channel-overlap.png differ diff --git a/site-src/implementations.md b/site-src/implementations.md index d33b3d16da..9013bc3495 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -1,37 +1,57 @@ # Implementations -This document tracks downstream implementations of Gateway API and provides status and resource references for them. +This document tracks downstream implementations and integrations of Gateway API and provides status and resource references for them. -Implementors of Gateway API are encouraged to update this document with status information about their implementations, the versions they cover, and documentation to help users get started. +Implementors and integrators of Gateway API are encouraged to update this document with status information about their implementations, the versions they cover, and documentation to help users get started. ## Implementation Status -- [Apache APISIX][1] (work in progress) -- [Contour][2] (alpha) -- [Emissary-Ingress (Ambassador API Gateway)][3] (alpha) -- [Gloo Edge 2.0][4] (work in progress) -- [Google Kubernetes Engine][5] (public preview) -- [HAProxy Ingress][6] (alpha) -- [HashiCorp Consul][7] -- [Istio][8] (alpha) -- [Kong][9] (alpha) -- [Traefik][10] (alpha) - -[1]:#apisix -[2]:#contour -[3]:#emissary-ingress-ambassador-api-gateway -[4]:#gloo-edge -[5]:#google-kubernetes-engine -[6]:#haproxy-ingress -[7]:#hashicorp-consul -[8]:#istio -[9]:#kong -[10]:#traefik - -## Project References + +- [Acnodal EPIC][1] (public preview) +- [Apache APISIX][2] (work in progress) +- [Contour][3] (alpha) +- [Emissary-Ingress (Ambassador API Gateway)][4] (alpha) +- [Gloo Edge 2.0][5] (work in progress) +- [Google Kubernetes Engine][6] (public preview) +- [HAProxy Ingress][7] (alpha) +- [HashiCorp Consul][8] +- [Istio][9] (alpha) +- [Kong][10] (alpha) +- [Kuma][11] (alpha) +- [NGINX Kubernetes Gateway][12] (pre-alpha) +- [Traefik][13] (alpha) + +## Integration Status +- [Flagger][14] (public preview) +- [cert-manager][15] (alpha) + +[1]:#acnodal-epic +[2]:#apisix +[3]:#contour +[4]:#emissary-ingress-ambassador-api-gateway +[5]:#gloo-edge +[6]:#google-kubernetes-engine +[7]:#haproxy-ingress +[8]:#hashicorp-consul +[9]:#istio +[10]:#kong +[11]:#kuma +[12]:#nginx-kubernetes-gateway +[13]:#traefik +[14]:#flagger +[15]:#cert-manager + +## Implementations In this section you will find specific links to blog posts, documentation and other Gateway API references for specific implementations. +### Acnodal EPIC +[EPIC][epic] is a Managed Application & API Gateway Service. The epic-controller installed in the cluster implements v1alpha2 and currently supports HTTPRoute. Defining Gateways and Routes creates a Gateway in the EPIC Service consisting of Envoy instances allocating public IP addresses and DNS for clients, and configures transport that sends request directly upstream to application endpoints in the cluster. EPIC is in public preview. + +Documentation can be found at [EPIC Application & API Gateway Service][epic] + +[epic]:https://www.epick8sgw.io + ### APISIX [Apache APISIX][apisix] is a dynamic, real-time, high-performance API Gateway. APISIX provides rich traffic management features such as load balancing, dynamic upstream, canary release, circuit breaking, authentication, observability, and more. @@ -130,13 +150,51 @@ Kong is actively working on an implementation of the Gateway API in the [Kong Ku [kic]:https://github.com/kong/kubernetes-ingress-controller [kong-gw-guide]:https://docs.konghq.com/kubernetes-ingress-controller/latest/guides/using-gateway-api/ +### Kuma + +[Kuma][kuma] is an open source service mesh. + +Kuma is actively working on an implementation of Gateway API specification for the Kuma builtin Gateway. Check the [Gateway API Documentation][kuma-1] for information on how to setup a Kuma builtin gateway using the Gateway API. + +[kuma]:https://kuma.io +[kuma-1]:https://kuma.io/docs/latest/explore/gateway-api/ + +### NGINX Kubernetes Gateway + +[NGINX Kubernetes Gateway][nginx-kubernetes-gateway] is an open-source project that provides an implementation of the Gateway API using [NGINX][nginx] as the data plane. The goal of this project is to implement the core Gateway APIs -- Gateway, GatewayClass, HTTPRoute, TCPRoute, TLSRoute, and UDPRoute -- to configure an HTTP or TCP/UDP load balancer, reverse-proxy, or API gateway for applications running on Kubernetes. NGINX Kubernetes Gateway is currently under development and supports a subset of the Gateway API. + +[nginx-kubernetes-gateway]:https://github.com/nginxinc/nginx-kubernetes-gateway +[nginx]:https://nginx.org/ + ### Traefik [Traefik][traefik] is an open source cloud-native application proxy. -Traefik currently supports the previous `v0.1.x` Gateway API specification, check the [Kubernetes Gateway Documentation][traefik-1] for information on how to deploy and use Traefik's Gateway implementation. +Traefik currently supports version `v1alpha2` (`v0.4.x`) of the Gateway API specification, check the [Kubernetes Gateway Documentation][traefik-1] for information on how to deploy and use Traefik's Gateway implementation. -Traefik is currently working on implementing TCP, status updates and documentation will be provided here as the work progresses. +Traefik is currently working on implementing UDP, and ReferenceGrant. Status updates and documentation will be provided here as the work progresses. [traefik]:https://traefik.io [traefik-1]:https://doc.traefik.io/traefik/routing/providers/kubernetes-gateway/ + +## Integrations + +In this section you will find specific links to blog posts, documentation and other Gateway API references for specific integrations. + +### Flagger + +[Flagger][flagger] is a progressive delivery tool that automates the release process for applications running on Kubernetes. + +Flagger can be used to automate canary deployments and A/B testing using Gateway API. It currently supports the `v1alpha2` spec of Gateway API. You can refer to [this tutorial][flagger-tutorial] to use Flagger with any implementation of Gateway API. + +[flagger]:https://flagger.app +[flagger-tutorial]:https://docs.flagger.app/tutorials/gatewayapi-progressive-delivery + +### cert-manager + +[cert-manager][cert-manager] is a tool to automate certificate management in cloud native environments. + +cert-manager can generate TLS certificates for Gateway resources. This is configured by adding annotations to a Gateway. It currently supports the `v1alpha2` spec of Gateway API. You can refer to the [cert-manager docs][cert-manager-docs] to try it out. + +[cert-manager]:https://cert-manager.io/ +[cert-manager-docs]:https://cert-manager.io/docs/usage/gateway/ diff --git a/site-src/index.md b/site-src/index.md index 95c4ca0753..5585eab60b 100644 --- a/site-src/index.md +++ b/site-src/index.md @@ -104,7 +104,7 @@ The Gateway API is a [SIG-Network](https://github.com/kubernetes/community/tree/master/sig-network) project being built to improve and standardize service networking in Kubernetes. Current and in-progress implementations include Contour, -Emissary-Ingress (Abassador API Gateway), Google Kubernetes Engine (GKE), Istio, +Emissary-Ingress (Ambassador API Gateway), Google Kubernetes Engine (GKE), Istio, Kong, and Traefik. Check out the [implementations reference](implementations.md) to see the latest projects & products that support Gateway. If you are interested in contributing to or diff --git a/site-src/references/releases.md b/site-src/references/releases.md deleted file mode 100644 index 3da94fe81c..0000000000 --- a/site-src/references/releases.md +++ /dev/null @@ -1,73 +0,0 @@ -# Release Policy - -Although Gateway API are an official Kubernetes project, and represent official -APIs, these APIs will not be installed by default on Kubernetes clusters at this -time. This project will use Custom Resource Definitions (CRDs) to represent the -new API types that Gateway API include. - -Similar to other Kubernetes APIs, these will go through a formal Kubernetes -Enhancement Proposal (KEP) review. Unlike other Kubernetes APIs, Gateway API -releases will be independent from Kubernetes releases initially. - -Gateway API releases will include four components: - -* Custom Resource Definitions to define the API. -* Go client libraries. -* Validation webhooks to implement cross field validations. -* Conversion webhooks to convert resources between API versions. - -## Versioning - -This project uses 2 different but related forms of versioning: - -- [Kubernetes API Versioning] (example: v1alpha1) -- [Semantic Versioning] (example: v0.1.0) - -Each new API version will be released with a new semantic version. For example, -v1alpha1 was released with v0.1.0. Before we release an API version, we may -provide some release candidates such as v0.1.0-rc1 as a way to evaluate a new -API version before it is formally released. All releases will be compatible with -[Go modules versioning]. - -As the API evolves, we will make intermediate releases that improve upon an -existing API version. These releases will be fully backwards compatible and will -be limited to either bug fixes or additions to the API. - -This project may release one or more additional alpha API versions. New alpha -API versions may include breaking changes such as removing or renaming fields or -resources. - -Following [Semantic Versioning], new patch releases will be limited to bug -fixes. New minor releases may include new fields or resources in addition to bug -fixes. New API versions will be released with new minor or major versions. - -Our changelog and release notes will always include both the semantic version -and API version(s) included in the release. - -[Kubernetes API Versioning]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md#alpha-beta-and-stable-versions -[Semantic Versioning]: https://semver.org/ -[Go modules versioning]: https://golang.org/ref/mod#versions - -> The first release candidate was tagged as `v1alpha1-rc1`. It predates this -documentation and is an exception. - -## Branching -This project will have frequent updates to the master branch. There are no -compatibility guarantees associated with code in any branch, including master, -until it has been released. For example, changes may be reverted before a -release is published. For the best results, use the latest published release of -this project. - -## Installation - -This project will be responsible for providing straightforward and reliable ways -to install releases of Gateway API. - -## Other Official Custom Resources - -This is a relatively new concept, and there is only one previous example of -official custom resources being used: -[VolumeSnapshots](https://kubernetes.io/blog/2018/10/09/introducing-volume-snapshot-alpha-for-kubernetes/). -Although VolumeSnapshot CRDs can be installed directly by CSI drivers that -support them, Gateway API must support multiple controllers per cluster, so the -CRDs will live in and be installed from this repo. diff --git a/site-src/v1alpha1/api-types/gateway.md b/site-src/v1alpha1/api-types/gateway.md index 54cb8401df..1a8f5ef664 100644 --- a/site-src/v1alpha1/api-types/gateway.md +++ b/site-src/v1alpha1/api-types/gateway.md @@ -1,5 +1,11 @@ # Gateway +!!! warning "v1alpha1 has been deprecated" + + Please upgrade to v1alpha2, v1alpha1 will be removed from Gateway API + in an upcoming release. + + A `Gateway` is 1:1 with the life cycle of the configuration of infrastructure. When a user creates a `Gateway`, some load balancing infrastructure is provisioned or configured (see below for details) by the `GatewayClass` diff --git a/site-src/v1alpha1/api-types/gatewayclass.md b/site-src/v1alpha1/api-types/gatewayclass.md index 09295ede3b..3de67c84da 100644 --- a/site-src/v1alpha1/api-types/gatewayclass.md +++ b/site-src/v1alpha1/api-types/gatewayclass.md @@ -1,5 +1,10 @@ # GatewayClass +!!! warning "v1alpha1 has been deprecated" + + Please upgrade to v1alpha2, v1alpha1 will be removed from Gateway API + in an upcoming release. + [GatewayClass][gatewayclass] is cluster-scoped resource defined by the infrastructure provider. This resource represents a class of Gateways that can be instantiated. diff --git a/site-src/v1alpha1/api-types/httproute.md b/site-src/v1alpha1/api-types/httproute.md index b3a4aba86e..a1d688ebe7 100644 --- a/site-src/v1alpha1/api-types/httproute.md +++ b/site-src/v1alpha1/api-types/httproute.md @@ -1,5 +1,10 @@ # HTTPRoute +!!! warning "v1alpha1 has been deprecated" + + Please upgrade to v1alpha2, v1alpha1 will be removed from Gateway API + in an upcoming release. + [HTTPRoute][httproute] is a Gateway API type for specifying routing behavior of HTTP requests from a Gateway listener to an API object, i.e. Service. @@ -168,8 +173,8 @@ unspecified, the rule performs no forwarding. If unspecified and no filters are specified that would result in a response being sent, a 503 error code is returned. -The following example forwards HTTP requests for prefiex `/bar` to service -"my-service1" on port `8080` and HTTP requests for prefex `/some/thing` with +The following example forwards HTTP requests for prefix `/bar` to service +"my-service1" on port `8080` and HTTP requests for prefix `/some/thing` with header `magic: foo` to service "my-service2" on port `8080`: ```yaml {% include 'v1alpha1/basic-http.yaml' %} @@ -228,7 +233,7 @@ A maximum of 100 Gateways can be represented in this list. If this list is full, there may be additional Gateways using this Route that are not included in the list. -### Merging +## Merging Multiple HTTPRoutes can be attached to a single Gateway resource. Importantly, only one Route rule may match each request. For more information on how conflict resolution applies to merging, refer to the [API specification][httprouterule]. diff --git a/site-src/v1alpha1/guides/getting-started.md b/site-src/v1alpha1/guides/getting-started.md index 56326b64ff..bb939c9303 100644 --- a/site-src/v1alpha1/guides/getting-started.md +++ b/site-src/v1alpha1/guides/getting-started.md @@ -1,5 +1,9 @@ # Getting started with Gateway APIs +!!! warning "v1alpha1 has been deprecated" + + Please upgrade to v1alpha2, v1alpha1 will be removed from Gateway API + in an upcoming release. **1.** **[Install a Gateway controller](#installing-a-gateway-controller)** _OR_ **[install the Gateway API CRDs manually](#installing-gateway-api-crds-manually)** diff --git a/site-src/v1alpha1/guides/http-routing.md b/site-src/v1alpha1/guides/http-routing.md index fd26afdae8..2c1f9a2d73 100644 --- a/site-src/v1alpha1/guides/http-routing.md +++ b/site-src/v1alpha1/guides/http-routing.md @@ -1,5 +1,10 @@ # HTTP routing +!!! warning "v1alpha1 has been deprecated" + + Please upgrade to v1alpha2, v1alpha1 will be removed from Gateway API + in an upcoming release. + The [HTTPRoute resource](/v1alpha1/api-types/httproute) allows you to match on HTTP traffic and direct it to Kubernetes backends. This guide shows how the HTTPRoute matches traffic on host, header, and path fields and forwards it to different diff --git a/site-src/v1alpha1/guides/multiple-ns.md b/site-src/v1alpha1/guides/multiple-ns.md index 10544ee53e..b0bb14c571 100644 --- a/site-src/v1alpha1/guides/multiple-ns.md +++ b/site-src/v1alpha1/guides/multiple-ns.md @@ -1,5 +1,10 @@ # Cross-Namespace routing +!!! warning "v1alpha1 has been deprecated" + + Please upgrade to v1alpha2, v1alpha1 will be removed from Gateway API + in an upcoming release. + The Gateway API has core support for cross Namespace routing. This is useful when more than one user or team is sharing the underlying networking infrastructure, yet control and configuration must be segmented to minimize access and fault diff --git a/site-src/v1alpha1/guides/simple-gateway.md b/site-src/v1alpha1/guides/simple-gateway.md index 241d299994..15551e49dc 100644 --- a/site-src/v1alpha1/guides/simple-gateway.md +++ b/site-src/v1alpha1/guides/simple-gateway.md @@ -1,5 +1,10 @@ # Deploying a simple Gateway +!!! warning "v1alpha1 has been deprecated" + + Please upgrade to v1alpha2, v1alpha1 will be removed from Gateway API + in an upcoming release. + The simplest possible deployment is a Gateway and Route resource which are deployed together by the same owner. This represents a similar kind of model used for Ingress. In this guide, a Gateway and HTTPRoute are deployed which diff --git a/site-src/v1alpha1/guides/tcp.md b/site-src/v1alpha1/guides/tcp.md index c1e330d09a..a1a5543c54 100644 --- a/site-src/v1alpha1/guides/tcp.md +++ b/site-src/v1alpha1/guides/tcp.md @@ -1,3 +1,8 @@ +!!! warning "v1alpha1 has been deprecated" + + Please upgrade to v1alpha2, v1alpha1 will be removed from Gateway API + in an upcoming release. + Gateway API is designed to work with multiple protocols. [TCPRoute](/v1alpha1/references/spec/#networking.x-k8s.io/v1alpha1.TCPRoute) is one such route which allows for managing TCP traffic. diff --git a/site-src/v1alpha1/guides/tls.md b/site-src/v1alpha1/guides/tls.md index c583f1ba41..d0305d3023 100644 --- a/site-src/v1alpha1/guides/tls.md +++ b/site-src/v1alpha1/guides/tls.md @@ -1,5 +1,10 @@ # TLS details +!!! warning "v1alpha1 has been deprecated" + + Please upgrade to v1alpha2, v1alpha1 will be removed from Gateway API + in an upcoming release. + Gateway API allow for a variety of ways to configure TLS. This document lays out various TLS settings and gives general guidelines on how to use them effectively. diff --git a/site-src/v1alpha1/guides/traffic-splitting.md b/site-src/v1alpha1/guides/traffic-splitting.md index dc82981946..b2b28c8072 100644 --- a/site-src/v1alpha1/guides/traffic-splitting.md +++ b/site-src/v1alpha1/guides/traffic-splitting.md @@ -1,5 +1,10 @@ # HTTP traffic splitting +!!! warning "v1alpha1 has been deprecated" + + Please upgrade to v1alpha2, v1alpha1 will be removed from Gateway API + in an upcoming release. + The [HTTPRoute resource](/v1alpha1/api-types/httproute) allows you to specify weights to shift traffic between different backends. This is useful for splitting traffic during rollouts, canarying changes, or for emergencies. The HTTPRoute diff --git a/site-src/v1alpha1/references/spec.md b/site-src/v1alpha1/references/spec.md index f60628062b..ac7043190b 100644 --- a/site-src/v1alpha1/references/spec.md +++ b/site-src/v1alpha1/references/spec.md @@ -1,3 +1,8 @@ # API Specification +!!! warning "v1alpha1 has been deprecated" + + Please upgrade to v1alpha2, v1alpha1 will be removed from Gateway API + in an upcoming release. + REPLACE_WITH_GENERATED_CONTENT diff --git a/site-src/v1alpha2/api-types/httproute.md b/site-src/v1alpha2/api-types/httproute.md index 43a599f449..20375746a8 100644 --- a/site-src/v1alpha2/api-types/httproute.md +++ b/site-src/v1alpha2/api-types/httproute.md @@ -27,7 +27,7 @@ here for implementations to support other types of parent resources. The following example shows how a Route would attach to the `acme-lb` Gateway: ```yaml -apiVersion: gateway.networking.k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: name: httproute-example @@ -56,7 +56,7 @@ rules and filters (optional). The following example defines hostname "my.example.com": ```yaml -apiVersion: gateway.networking.k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: name: httproute-example @@ -78,7 +78,7 @@ independent, i.e. this rule will be matched if any single match is satisfied. Take the following matches configuration as an example: ```yaml -apiVersion: gateway.networking.k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute ... matches: @@ -130,11 +130,11 @@ Specifying a core filter multiple times has unspecified or custom conformance. BackendRefs defines API objects where matching requests should be sent. If unspecified, the rule performs no forwarding. If unspecified and no filters -are specified that would result in a response being sent, a 503 error code +are specified that would result in a response being sent, a 404 error code is returned. -The following example forwards HTTP requests for prefiex `/bar` to service -"my-service1" on port `8080` and HTTP requests for prefex `/some/thing` with +The following example forwards HTTP requests for prefix `/bar` to service +"my-service1" on port `8080` and HTTP requests for prefix `/some/thing` with header `magic: foo` to service "my-service2" on port `8080`: ```yaml {% include 'v1alpha2/basic-http.yaml' %} @@ -170,7 +170,7 @@ appropriate when the route is modified. The following example indicates HTTPRoute "http-example" has been accepted by Gateway "gw-example" in namespace "gw-example-ns": ```yaml -apiVersion: gateway.networking.k8s.io/v1alpha1 +apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: name: http-example @@ -185,7 +185,7 @@ status: status: "True" ``` -### Merging +## Merging Multiple HTTPRoutes can be attached to a single Gateway resource. Importantly, only one Route rule may match each request. For more information on how conflict resolution applies to merging, refer to the [API specification][httprouterule]. diff --git a/site-src/v1alpha2/api-types/referencepolicy.md b/site-src/v1alpha2/api-types/referencegrant.md similarity index 74% rename from site-src/v1alpha2/api-types/referencepolicy.md rename to site-src/v1alpha2/api-types/referencegrant.md index 81564c23b1..7a8290ff80 100644 --- a/site-src/v1alpha2/api-types/referencepolicy.md +++ b/site-src/v1alpha2/api-types/referencegrant.md @@ -1,22 +1,26 @@ -# ReferencePolicy +# ReferenceGrant -A ReferencePolicy can be used to enable cross namespace references within +!!! note + This resource was originally named "ReferencePolicy". It was renamed + to "ReferenceGrant" to avoid any confusion with policy attachment. + +A ReferenceGrant can be used to enable cross namespace references within Gateway API. In particular, Routes may forward traffic to backends in other namespaces, or Gateways may refer to Secrets in another namespace. -![Reference Policy](/v1alpha2/images/referencepolicy-simple.png) +![Reference Grant](/v1alpha2/images/referencegrant-simple.png) In the past, we've seen that forwarding traffic across namespace boundaries is a -desired feature, but without a safeguard like ReferencePolicy, +desired feature, but without a safeguard like ReferenceGrant, [vulnerabilities](https://github.com/kubernetes/kubernetes/issues/103675) can emerge. If an object is referred to from outside its namespace, the object's owner must -create a ReferencePolicy resource to explicitly allow that reference. Without a -ReferencePolicy, a cross namespace reference is invalid. +create a ReferenceGrant resource to explicitly allow that reference. Without a +ReferenceGrant, a cross namespace reference is invalid. ## Structure -Fundamentally a ReferencePolicy is made up of two lists, a list of resources +Fundamentally a ReferenceGrant is made up of two lists, a list of resources references may come from, and a list of resources that may be referenced. The `from` list allows you to specify the group, kind, and namespace of @@ -24,12 +28,12 @@ resources that may reference items described in the `to` list. The `to` list allows you to specify the group and kind of resources that may be referenced by items described in the `from` list. The namespace is not necessary -in the `to` list because a ReferencePolicy can only be used to allow references -to resources in the same namespace as the ReferencePolicy. +in the `to` list because a ReferenceGrant can only be used to allow references +to resources in the same namespace as the ReferenceGrant. ## Example The following example shows how a HTTPRoute in namespace `foo` can reference a -Service in namespace `bar`. In this example a ReferencePolicy in the `bar` +Service in namespace `bar`. In this example a ReferenceGrant in the `bar` namespace explicitly allows references to Services from HTTPRoutes in the `foo` namespace. @@ -47,7 +51,7 @@ spec: - name: bar namespace: bar --- -kind: ReferencePolicy +kind: ReferenceGrant metadata: name: bar namespace: bar @@ -64,8 +68,8 @@ spec: ## API design decisions While the API is simplistic in nature, it comes with a few notable decisions: -1. Each ReferencePolicy only supports a single From and To section. Additional - trust relationships must be modeled with additional ReferencePolicy +1. Each ReferenceGrant only supports a single From and To section. Additional + trust relationships must be modeled with additional ReferenceGrant resources. 1. Resource names are intentionally excluded from this policy for simplicity and because they rarely provide any meaningful protection. A user that is able to @@ -77,25 +81,25 @@ While the API is simplistic in nature, it comes with a few notable decisions: other. This makes it impossible for them to conflict with each other. Please see the [API -Specification](/v1alpha2/references/spec#gateway.networking.k8s.io/v1alpha2.ReferencePolicy) -for more details on how specific ReferencePolicy fields are interpreted. +Specification](/v1alpha2/references/spec#gateway.networking.k8s.io/v1alpha2.ReferenceGrant) +for more details on how specific ReferenceGrant fields are interpreted. ## Exceptions Cross namespace Route -> Gateway binding follows a slightly different pattern where the handshake mechanism is built into the Gateway resource. For more information on that approach, refer to the relevant [Security Model documentation](/concepts/security-model). Although conceptually similar to -ReferencePolicy, this configuration is built directly into Gateway Listeners, +ReferenceGrant, this configuration is built directly into Gateway Listeners, and allows for fine-grained per Listener configuration that would not be -possible with ReferencePolicy. +possible with ReferenceGrant. -There are some situations where it MAY be acceptable to ignore ReferencePolicy +There are some situations where it MAY be acceptable to ignore ReferenceGrant in favor of some other security mechanism. This MAY only be done if other mechanisms like NetworkPolicy can effectively limit cross-namespace references by the implementation. An implementation choosing to make this exception MUST clearly document that -ReferencePolicy is not honored by their implementations and detail which +ReferenceGrant is not honored by their implementations and detail which alternative safeguards are available. Note that this is unlikely to apply to ingress implementations of the API and will not apply to all mesh implementations. @@ -103,12 +107,12 @@ implementations. For an example of the risks involved in cross-namespace references, refer to [CVE-2021-25740](https://github.com/kubernetes/kubernetes/issues/103675). Implementations of this API need to be very careful to avoid confused deputy -attacks. ReferencePolicy provides a safeguard for that. Exceptions MUST only be +attacks. ReferenceGrant provides a safeguard for that. Exceptions MUST only be made by implementations that are absolutely certain that other equally effective safeguards are in place. ## Conformance Level -ReferencePolicy support is a "CORE" conformance level requirement for +ReferenceGrant support is a "CORE" conformance level requirement for cross-namespace references that originate from the following objects: - HTTPRoute diff --git a/site-src/v1alpha2/contributing/devguide.md b/site-src/v1alpha2/contributing/devguide.md index 916b64e7a0..1cb0241084 100644 --- a/site-src/v1alpha2/contributing/devguide.md +++ b/site-src/v1alpha2/contributing/devguide.md @@ -59,6 +59,18 @@ You can kick off an overall build from the top-level makefile: make ``` +## Adding Experimental Fields + +Starting with v0.5.0, all additions to the API must start in the experimental +release channel. Experimental fields must be marked with the +`` annotation in Go type definitions. Gateway API CRD +generation will exclude these fields from stable CRDs. + +If experimental fields are removed or renamed, the original field name should be +removed from the go struct, with a tombstone comment +([example](https://github.com/kubernetes/kubernetes/blob/707b8b6efd1691b84095c9f995f2c259244e276c/staging/src/k8s.io/api/core/v1/types.go#L4444-L4445)) +ensuring the field name will not be reused. + ## Install CRDs To install gateway-api CRDs into a Kubernetes cluster: @@ -122,7 +134,6 @@ INFO - Building documentation... ... ``` - [mkdocs]: https://www.mkdocs.org/ [mkdocs]: https://www.mkdocs.org/ [Netlify]: https://netlify.com/ [gateway-api.sigs.k8s.io]: https://gateway-api.sigs.k8s.io diff --git a/site-src/v1alpha2/guides/getting-started.md b/site-src/v1alpha2/guides/getting-started.md index c2592ce364..5a09f66060 100644 --- a/site-src/v1alpha2/guides/getting-started.md +++ b/site-src/v1alpha2/guides/getting-started.md @@ -1,7 +1,7 @@ # Getting started with Gateway APIs **1.** **[Install a Gateway controller](#installing-a-gateway-controller)** - _OR_ **[install the Gateway API CRDs manually](#installing-gateway-api-crds-manually)** + _OR_ **[install the Gateway API CRDs manually](#installing-a-gateway-api-bundle)** _THEN_ @@ -21,33 +21,43 @@ Gateway API. By installing a Gateway controller in your Kubernetes cluster, you can try out the guides above. This will demonstrate that the desired routing configuration is actually being implemented by your Gateway resources (and the network infrastructure that your Gateway resources represent). Note that many -of the Gateway controller setups will install and remove the Gateway API CRDs +of the Gateway controller setups will install and remove the Gateway API bundle for you. -## Installing Gateway API CRDs manually +## Installing a Gateway API Bundle -The following command will install the Gateway API CRDs. This includes the +A Gateway API bundle represents the set of CRDs and validating webhook +associated with a version of Gateway API. + +### Install the CRDs + +The following command will install the Gateway API CRDs. This includes GatewayClass, Gateway, HTTPRoute, TCPRoute, and more. Note that a running Gateway controller in your Kubernetes cluster is required to actually act on these resources. Installing the CRDs will just allow you to see and apply the -resources, though they won't do anything. +resources, but they won't do anything without a controller implementing them. ``` -kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.4.0" \ -| kubectl apply -f - +kubectl apply -k "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.4.3" ``` -After you're done, you can clean up after yourself by uninstalling the -Gateway API CRDs. The following command will remove all GatewayClass, Gateway, -and associated resources in your cluster. If these resources are in-use or -if they were installed by a Gateway controller, then do not uninstall them. -This will uninstall the Gateway API CRDs for the entire cluster. Do not do -this if they might be in-use by someone else as this will break anything using -these resources. +### Install the Webhook +The validating webhook included with Gateway API is still in active development +and not as stable as other components included in the API. We expect this +webhook to reach a greater level of stability in an upcoming v0.4 release. +Until that point, the webhook can be installed with the following kubectl +commands: ``` -kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.4.0" \ -| kubectl delete -f - +kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v0.4.3/deploy/admission_webhook.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v0.4.3/deploy/certificate_config.yaml ``` +### Cleanup +After you're done, you can clean up after yourself by uninstalling the Gateway +API CRDs and webhook by replacing "apply" with "delete" in the commands above. +If these resources are in-use or if they were installed by a Gateway controller, +then do not uninstall them. This will uninstall the Gateway API resources for +the entire cluster. Do not do this if they might be in-use by someone else as +this will break anything using these resources. diff --git a/site-src/v1alpha2/guides/tcp.md b/site-src/v1alpha2/guides/tcp.md index 6ad3a9aa8c..858df72b0f 100644 --- a/site-src/v1alpha2/guides/tcp.md +++ b/site-src/v1alpha2/guides/tcp.md @@ -43,28 +43,6 @@ In this way each `TCPRoute` "attaches" itself to a different port on the `Gateway` so that the service `my-foo-service` is taking traffic for port `8080` from outside the cluster and `my-bar-service` takes the port `8090` traffic. -## Alternatives: Routing Using Traffic Matching - -!!! info "Experimental Channel" - - This functionality is currently only included in the "Experimental" channel - of Gateway API. For more information on release channels, refer to the - [related documentation](https://gateway-api.sigs.k8s.io/concepts/versioning/#adding-experimental-fields). - -In addition to simply matching traffic based on a Gateway's listeners (as seen -in the above examples) a `TCPRoute` can also match further on the traffic bound -for that listener: - -``` -{% include 'experimental/v1alpha2/traffic-matching-tcp.yaml' %} -``` - -In the above example the `matches` option for the `TCPRoute` rules enables the -route to only serve the traffic that matches specified destination and/or source -address patterns. In this way separate `TCPRoute` objects can be responsible -for routing different traffic on the same `Gateway` listener and can enable -significant flexibility for pure TCP routing. - [tcproute]:/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.TCPRoute [tcp]:https://datatracker.ietf.org/doc/html/rfc793 [httproute]:/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.HTTPRoute diff --git a/site-src/v1alpha2/guides/tls.md b/site-src/v1alpha2/guides/tls.md index 685a74db26..b57deaf421 100644 --- a/site-src/v1alpha2/guides/tls.md +++ b/site-src/v1alpha2/guides/tls.md @@ -87,8 +87,8 @@ Since a specific match takes priority, the Gateway will serve #### Cross namespace certificate references In this example, the Gateway is configured to reference a certificate in a -different namespace. This is allowed by the ReferencePolicy created in the -target namespace. Without that ReferencePolicy, the cross-namespace reference +different namespace. This is allowed by the ReferenceGrant created in the +target namespace. Without that ReferenceGrant, the cross-namespace reference would be invalid. ```yaml diff --git a/site-src/v1alpha2/images/referencepolicy-simple.png b/site-src/v1alpha2/images/referencegrant-simple.png similarity index 100% rename from site-src/v1alpha2/images/referencepolicy-simple.png rename to site-src/v1alpha2/images/referencegrant-simple.png