From 02ddf1ebaa7a1d257940389c78ba033d2c2eae6d Mon Sep 17 00:00:00 2001 From: Nick Young Date: Thu, 28 Sep 2023 03:42:00 +0000 Subject: [PATCH 1/3] Update GEP-713 with status struct design Signed-off-by: Nick Young --- geps/gep-713.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/geps/gep-713.md b/geps/gep-713.md index c677541c76..82138219ee 100644 --- a/geps/gep-713.md +++ b/geps/gep-713.md @@ -910,7 +910,67 @@ plugin. This is already part of the API pattern, but is being lifted to more prominience here. -#### Standard status Condition +#### Standard status struct + +Status: Recommended + +Policy objects SHOULD use the upstream `PolicyAncestorStatus` struct in their respective +Status structs. Please see the included `PolicyAncestorStatus` struct, and its use in +the `BackendTLSPolicy` object for detailed examples. Included here is a representative +version. + +This is an `Ancestor` status rather than a `Parent` status, as in the Route status +because for Policy attachment, the relevant object may or may not be the direct +parent. + +For example, `BackendTLSPolicy` directly attaches to a Service, which may be included +in multiple Routes, in multiple Gateways. However, the status of the `BackendTLSPolicy` +will be different only at the Gateway level, so Gateway is the relevant Ancestor +for the status. + +Each Gateway that has a Route that includes a backend with an attached `BackendTLSPolicy` +MUST have a separate `PolicyAncestorStatus` section in the `BackendTLSPolicy`'s +`status.ancestors` stanza, which mandates that entries must be distinct using the +combination of the `AncestorRef` and the `ControllerName` fields as a key. + +See [GEP-1897][gep-1897] for the exact details. + +[gep-1897]: /geps/gep-1897 + +```go +// PolicyAncestorStatus describes the status of a route with respect to an +// associated Parent. +type PolicyAncestorStatus struct { + // AncestorRef corresponds with a ParentRef in the spec that this + // RouteParentStatus struct describes the status of. + AncestorRef 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 Policy with respect to the given Ancestor. + // + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} +``` + +#### Standard status Condition on Policy-affected objects Support: Provisional From fa5cafbd34295aa3e5794567921439bb07e8e6df Mon Sep 17 00:00:00 2001 From: Nick Young Date: Sun, 1 Oct 2023 03:02:10 +0000 Subject: [PATCH 2/3] Finish PolicyStatus struct design and add to the API Signed-off-by: Nick Young --- apis/v1alpha2/policy_types.go | 76 +++++++++++++++++++++++++++++++++++ geps/gep-713.md | 52 +++++++++++++++++++++++- 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/apis/v1alpha2/policy_types.go b/apis/v1alpha2/policy_types.go index 6d1d8af97d..cfd31f9421 100644 --- a/apis/v1alpha2/policy_types.go +++ b/apis/v1alpha2/policy_types.go @@ -16,6 +16,8 @@ limitations under the License. package v1alpha2 +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + const ( // PolicyLabelKey is the label whose presence identifies a CRD that the // Gateway API Policy attachment model. The value of the label SHOULD be one @@ -29,6 +31,8 @@ const ( PolicyLabelKey = "gateway.networking.k8s.io/policy" ) + + // PolicyTargetReference identifies an API object to apply a direct or // inherited policy to. This should be used as part of Policy resources // that can target Gateway API resources. For more information on how this @@ -120,3 +124,75 @@ const ( // policy is attached to an invalid target resource. PolicyReasonTargetNotFound PolicyConditionReason = "TargetNotFound" ) + +// PolicyAncestorStatus describes the status of a route with respect to an +// associated Ancestor. +// +// The object that a Policy attaches to (the object in its TargetRef) is its +// _parent_, and any other objects above it in an object hierarchy are its +// _ancestors_. +// +// For some Policies, particularly Direct Attached Policies, the relevant object +// that distinguishes its status is not necessarily the parent object. +// +// For example, in BackendTLSPolicy, the Policy attaches to a Service that is +// used as a backend in a HTTPRoute that is itself attached to a Gateway. +// In this case, the relevant object for status is the Gateway, and that is the +// ancestor object referred to in this status. +// +// Note that a parent is also an ancestor, so for objects where the parent is the +// relevant object for status, this struct SHOULD still be used. +type PolicyAncestorStatus struct { + // AncestorRef corresponds with a ParentRef in the spec that this + // RouteParentStatus struct describes the status of. + AncestorRef ParentReference `json:"ancestorRef"` + + // 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 Policy with respect to the given Ancestor. + // + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// PolicyStatus defines the common attributes that all Policies should include within +// their status. +type PolicyStatus struct { + // Ancestors is a list of ancestor resources (usually Gateways) that are + // associated with the route, and the status of the route with respect to + // each ancestor. When this route attaches to a parent, the controller that + // manages the parent and the ancestors MUST add an entry to this list when + // the controller first sees the route and SHOULD update the entry as + // appropriate when the relevant ancestor is modified. + // + // Note that choosing the relevant ancestor is left to the Policy designers; + // an important part of Policy design is designing the right object level at + // which to namespace this status. + // + // Note also 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 ancestor status for the parent resources they are + // responsible for. + // + // A maximum of 32 ancestors will be represented in this list. An empty list + // means the Policy is not relevant for any ancestors. + // + // +kubebuilder:validation:MaxItems=32 + Ancestors []PolicyAncestorStatus `json:"ancestors"` +} \ No newline at end of file diff --git a/geps/gep-713.md b/geps/gep-713.md index 82138219ee..fb48720144 100644 --- a/geps/gep-713.md +++ b/geps/gep-713.md @@ -939,11 +939,26 @@ See [GEP-1897][gep-1897] for the exact details. ```go // PolicyAncestorStatus describes the status of a route with respect to an -// associated Parent. +// associated Ancestor. +// +// The object that a Policy attaches to (the object in its TargetRef) is its +// _parent_, and any other objects above it in an object hierarchy are its +// _ancestors_. +// +// For some Policies, particularly Direct Attached Policies, the relevant object +// that distinguishes its status is not necessarily the parent object. +// +// For example, in BackendTLSPolicy, the Policy attaches to a Service that is +// used as a backend in a HTTPRoute that is itself attached to a Gateway. +// In this case, the relevant object for status is the Gateway, and that is the +// ancestor object referred to in this status. +// +// Note that a parent is also an ancestor, so for objects where the parent is the +// relevant object for status, this struct SHOULD still be used. type PolicyAncestorStatus struct { // AncestorRef corresponds with a ParentRef in the spec that this // RouteParentStatus struct describes the status of. - AncestorRef ParentReference `json:"parentRef"` + AncestorRef ParentReference `json:"ancestorRef"` // ControllerName is a domain/path string that indicates the name of the // controller that wrote this status. This corresponds with the @@ -968,8 +983,41 @@ type PolicyAncestorStatus struct { // +kubebuilder:validation:MaxItems=8 Conditions []metav1.Condition `json:"conditions,omitempty"` } + + +// PolicyStatus defines the common attributes that all Policies SHOULD include +// within their status. +type PolicyStatus struct { + // Ancestors is a list of ancestor resources (usually Gateways) that are + // associated with the route, and the status of the route with respect to + // each ancestor. When this route attaches to a parent, the controller that + // manages the parent and the ancestors MUST add an entry to this list when + // the controller first sees the route and SHOULD update the entry as + // appropriate when the relevant ancestor is modified. + // + // Note that choosing the relevant ancestor is left to the Policy designers; + // an important part of Policy design is designing the right object level at + // which to namespace this status. + // + // Note also 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 ancestor status for the parent resources they are + // responsible for. + // + // A maximum of 32 ancestors will be represented in this list. An empty list + // means the Policy is not relevant for any ancestors. + // + // +kubebuilder:validation:MaxItems=32 + Ancestors []PolicyAncestorStatus `json:"ancestors"` +} ``` +##### Design considerations + +This is recommended as the base for Policy object's status. As Policy Attachment +is a pattern, not an API, "recommended" is the strongest we can make this, but +we believe that standardizing this will help a lot with discoverability. + #### Standard status Condition on Policy-affected objects Support: Provisional From 14197584076cbc6853caf4a6cef29d6d5810595c Mon Sep 17 00:00:00 2001 From: Nick Young Date: Sun, 1 Oct 2023 03:59:31 +0000 Subject: [PATCH 3/3] Add BackendTLSPolicy implementation and make generate Signed-off-by: Nick Young --- apis/v1alpha2/backendtlspolicy_types.go | 148 ++++++ apis/v1alpha2/policy_types.go | 55 +- apis/v1alpha2/zz_generated.deepcopy.go | 149 ++++++ apis/v1alpha2/zz_generated.register.go | 2 + apis/v1beta1/httproute_types.go | 8 + apis/v1beta1/object_reference_types.go | 39 ++ apis/v1beta1/shared_types.go | 4 + apis/v1beta1/zz_generated.deepcopy.go | 20 + ....networking.k8s.io_backendtlspolicies.yaml | 492 ++++++++++++++++++ .../gateway.networking.k8s.io_tcproutes.yaml | 6 +- .../gateway.networking.k8s.io_tlsroutes.yaml | 6 +- .../gateway.networking.k8s.io_udproutes.yaml | 6 +- geps/gep-1897.md | 27 +- geps/gep-713.md | 50 +- mkdocs.yml | 2 +- .../typed/apis/v1alpha2/apis_client.go | 5 + .../typed/apis/v1alpha2/backendtlspolicy.go | 195 +++++++ .../apis/v1alpha2/fake/fake_apis_client.go | 4 + .../v1alpha2/fake/fake_backendtlspolicy.go | 141 +++++ .../apis/v1alpha2/generated_expansion.go | 2 + .../apis/v1alpha2/backendtlspolicy.go | 90 ++++ .../apis/v1alpha2/interface.go | 7 + .../informers/externalversions/generic.go | 2 + .../listers/apis/v1alpha2/backendtlspolicy.go | 99 ++++ .../apis/v1alpha2/expansion_generated.go | 8 + 25 files changed, 1505 insertions(+), 62 deletions(-) create mode 100644 apis/v1alpha2/backendtlspolicy_types.go create mode 100644 config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml create mode 100644 pkg/client/clientset/versioned/typed/apis/v1alpha2/backendtlspolicy.go create mode 100644 pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_backendtlspolicy.go create mode 100644 pkg/client/informers/externalversions/apis/v1alpha2/backendtlspolicy.go create mode 100644 pkg/client/listers/apis/v1alpha2/backendtlspolicy.go diff --git a/apis/v1alpha2/backendtlspolicy_types.go b/apis/v1alpha2/backendtlspolicy_types.go new file mode 100644 index 0000000000..ba22926e03 --- /dev/null +++ b/apis/v1alpha2/backendtlspolicy_types.go @@ -0,0 +1,148 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "sigs.k8s.io/gateway-api/apis/v1beta1" +) + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:resource:categories=gateway-api,shortName=btlspolicy +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// BackendTLSPolicy provides a way to configure how a Gateway +// connects to a Backend via TLS. +type BackendTLSPolicy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of BackendTLSPolicy. + Spec BackendTLSPolicySpec `json:"spec"` + + // Status defines the current state of BackendTLSPolicy. + Status PolicyStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// BackendTLSPolicyList contains a list of BackendTLSPolicies +type BackendTLSPolicyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []BackendTLSPolicy `json:"items"` +} + +// BackendTLSPolicySpec defines the desired state of +// BackendTLSPolicy. +// Note: BackendTLSPolicy is a Direct Attached Policy only. +// +// Support: Extended +type BackendTLSPolicySpec struct { + // TargetRef identifies an API object to apply the policy to. + // Only Services have Extended support. Implementations MAY support + // additional objects, with Implementation Specific support. + // Note that this config applies to the entire referenced resource + // by default, but this default may change in the future to provide + // a more granular application of the policy. + // + // Support: Extended for Kubernetes Service + // + // Support: Implementation-specific for any other resource + // + TargetRef PolicyTargetReferenceWithSectionName `json:"targetRef"` + + // TLS contains backend TLS policy configuration. + TLS BackendTLSPolicyConfig `json:"tls"` +} + +// BackendTLSPolicyConfig contains backend TLS policy configuration. +// +kubebuilder:validation:XValidation:message="must not contain both CertRefs and StandardCerts",rule="(has(self.caCertRefs) && size(self.caCertRefs) > 0 && has(self.wellKnownCACerts) && self.wellKnownCACerts != \"\")" +// +kubebuilder:validation:XValidation:message="must specify either CertRefs or StandardCerts",rule="!(has(self.caCertRefs) && size(self.caCertRefs) > 0 || has(self.wellKnownCACerts) && self.wellKnownCACerts != \"\")" +type BackendTLSPolicyConfig struct { + // CACertRefs contains one or more references to Kubernetes objects that + // contain a PEM-encoded TLS CA certificate bundle, which is used to + // validate a TLS handshake between the Gateway and backend Pod. + // + // If CACertRefs is empty or unspecified, then StandardCerts must + // be specified. Only one of CACertRefs or StandardCerts may be + // specified, not both. + // + // If CACertRefs is empty or unspecified, then system trusted + // certificates should be used. If there are none, or the + // implementation doesn't define system trusted certificates, + // then a TLS connection must fail. + // + // References to a resource in a different namespace are + // invalid for the moment, although we will revisit this + // in the future. + // + // A single CACertRef to a Kubernetes ConfigMap kind has "Core" + // support. Implementations MAY choose to support attaching + // multiple certificates to a backend, but this behavior is + // implementation-specific. + // + // Support: Core - An optional single reference to a Kubernetes + // ConfigMap, with the CA certificate in a key named `ca.crt`. + // + // Support: Implementation-specific (More than one reference, or other kinds + // of resources). + // + // +kubebuilder:validation:MaxItems=8 + // +optional + CACertRefs []v1beta1.ObjectReference `json:"caCertRefs,omitempty"` + + // WellKnownCACerts specifies whether system CA certificates may + // be used in the TLS handshake between the gateway and + // backend pod. + // + // If WellKnownCACerts is unspecified or set to "", then CACertRefs must + // be specified with at least one entry for a valid configuration. + // Only one of CACertRefs or WellKnownCACerts may be specified, not both. + // + // WellKnownCACerts must be set to "System" when CACertRefs is unspecified. + // + // + // Support: Core for "System" + // + // + // +optional + WellKnownCACerts *WellKnownCACertType `json:"wellKnownCACerts,omitempty"` + + // Hostname is used for two purposes in the connection between Gateways and + // backends: + // + // 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). + // 2. Hostname MUST be used for authentication and MUST match the certificate + // served by the matching backend. + // + // Support: Core + Hostname v1beta1.PreciseHostname `json:"hostname"` +} + +// WellKnownCACertType is the type of CA certificate that will be used when +// the TLS.caCertRefs is unspecified. +// +kubebuilder:validation:Enum=System +type WellKnownCACertType string + +const ( + // Indicates that standard system CA certificates should be used. + WellKnownCACertSystem WellKnownCACertType = "System" +) diff --git a/apis/v1alpha2/policy_types.go b/apis/v1alpha2/policy_types.go index cfd31f9421..0d208d6c10 100644 --- a/apis/v1alpha2/policy_types.go +++ b/apis/v1alpha2/policy_types.go @@ -31,8 +31,6 @@ const ( PolicyLabelKey = "gateway.networking.k8s.io/policy" ) - - // PolicyTargetReference identifies an API object to apply a direct or // inherited policy to. This should be used as part of Policy resources // that can target Gateway API resources. For more information on how this @@ -128,12 +126,22 @@ const ( // PolicyAncestorStatus describes the status of a route with respect to an // associated Ancestor. // -// The object that a Policy attaches to (the object in its TargetRef) is its -// _parent_, and any other objects above it in an object hierarchy are its -// _ancestors_. -// -// For some Policies, particularly Direct Attached Policies, the relevant object -// that distinguishes its status is not necessarily the parent object. +// Ancestors refer to objects that are either the Target of a policy or above it +// in terms of object hierarchy. For example, if a policy targets a Service, the +// Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and +// the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most +// useful object to place Policy status on, so we recommend that implementations +// SHOULD use Gateway as the PolicyAncestorStatus object unless the designers +// have a _very_ good reason otherwise. +// +// In the context of policy attachment, the Ancestor is used to distinguish which +// resource results in a distinct application of this policy. For example, if a policy +// targets a Service, it may have a distinct result per attached Gateway. +// +// Policies targeting the same resource may have different effects depending on the +// ancestors of those resources. For example, different Gateways targeting the same +// Service may have different capabilities, especially if they have different underlying +// implementations. // // For example, in BackendTLSPolicy, the Policy attaches to a Service that is // used as a backend in a HTTPRoute that is itself attached to a Gateway. @@ -142,9 +150,12 @@ const ( // // Note that a parent is also an ancestor, so for objects where the parent is the // relevant object for status, this struct SHOULD still be used. +// +// This struct is intended to be used in a slice that's effectively a map, +// with a composite key made up of the AncestorRef and the ControllerName. type PolicyAncestorStatus struct { // AncestorRef corresponds with a ParentRef in the spec that this - // RouteParentStatus struct describes the status of. + // PolicyAncestorStatus struct describes the status of. AncestorRef ParentReference `json:"ancestorRef"` // ControllerName is a domain/path string that indicates the name of the @@ -175,24 +186,30 @@ type PolicyAncestorStatus struct { // their status. type PolicyStatus struct { // Ancestors is a list of ancestor resources (usually Gateways) that are - // associated with the route, and the status of the route with respect to - // each ancestor. When this route attaches to a parent, the controller that + // associated with the policy, and the status of the policy with respect to + // each ancestor. When this policy attaches to a parent, the controller that // manages the parent and the ancestors MUST add an entry to this list when - // the controller first sees the route and SHOULD update the entry as + // the controller first sees the policy and SHOULD update the entry as // appropriate when the relevant ancestor is modified. // // Note that choosing the relevant ancestor is left to the Policy designers; // an important part of Policy design is designing the right object level at // which to namespace this status. // - // Note also 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 ancestor status for the parent resources they are - // responsible for. + // Note also that implementations MUST ONLY populate ancestor status for + // the Ancestor resources they are responsible for. Implementations MUST + // use the ControllerName field to uniquely identify the entries in this list + // that they are responsible for. + // + // Note that to achieve this, the list of PolicyAncestorStatus structs + // MUST be treated as a map with a composite key, made up of the AncestorRef + // and ControllerName fields combined. // - // A maximum of 32 ancestors will be represented in this list. An empty list + // A maximum of 16 ancestors will be represented in this list. An empty list // means the Policy is not relevant for any ancestors. // - // +kubebuilder:validation:MaxItems=32 + // If this slice is full, implementations MUST NOT add further entries. + // + // +kubebuilder:validation:MaxItems=16 Ancestors []PolicyAncestorStatus `json:"ancestors"` -} \ No newline at end of file +} diff --git a/apis/v1alpha2/zz_generated.deepcopy.go b/apis/v1alpha2/zz_generated.deepcopy.go index 890f57faf3..f15fdf3b9c 100644 --- a/apis/v1alpha2/zz_generated.deepcopy.go +++ b/apis/v1alpha2/zz_generated.deepcopy.go @@ -21,10 +21,114 @@ limitations under the License. package v1alpha2 import ( + "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/gateway-api/apis/v1beta1" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendTLSPolicy) DeepCopyInto(out *BackendTLSPolicy) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSPolicy. +func (in *BackendTLSPolicy) DeepCopy() *BackendTLSPolicy { + if in == nil { + return nil + } + out := new(BackendTLSPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BackendTLSPolicy) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendTLSPolicyConfig) DeepCopyInto(out *BackendTLSPolicyConfig) { + *out = *in + if in.CACertRefs != nil { + in, out := &in.CACertRefs, &out.CACertRefs + *out = make([]v1beta1.ObjectReference, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.WellKnownCACerts != nil { + in, out := &in.WellKnownCACerts, &out.WellKnownCACerts + *out = new(WellKnownCACertType) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSPolicyConfig. +func (in *BackendTLSPolicyConfig) DeepCopy() *BackendTLSPolicyConfig { + if in == nil { + return nil + } + out := new(BackendTLSPolicyConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendTLSPolicyList) DeepCopyInto(out *BackendTLSPolicyList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]BackendTLSPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSPolicyList. +func (in *BackendTLSPolicyList) DeepCopy() *BackendTLSPolicyList { + if in == nil { + return nil + } + out := new(BackendTLSPolicyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BackendTLSPolicyList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendTLSPolicySpec) DeepCopyInto(out *BackendTLSPolicySpec) { + *out = *in + in.TargetRef.DeepCopyInto(&out.TargetRef) + in.TLS.DeepCopyInto(&out.TLS) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSPolicySpec. +func (in *BackendTLSPolicySpec) DeepCopy() *BackendTLSPolicySpec { + if in == nil { + return nil + } + out := new(BackendTLSPolicySpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GRPCBackendRef) DeepCopyInto(out *GRPCBackendRef) { *out = *in @@ -476,6 +580,51 @@ func (in *HTTPRouteList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyAncestorStatus) DeepCopyInto(out *PolicyAncestorStatus) { + *out = *in + in.AncestorRef.DeepCopyInto(&out.AncestorRef) + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyAncestorStatus. +func (in *PolicyAncestorStatus) DeepCopy() *PolicyAncestorStatus { + if in == nil { + return nil + } + out := new(PolicyAncestorStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyStatus) DeepCopyInto(out *PolicyStatus) { + *out = *in + if in.Ancestors != nil { + in, out := &in.Ancestors, &out.Ancestors + *out = make([]PolicyAncestorStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyStatus. +func (in *PolicyStatus) DeepCopy() *PolicyStatus { + if in == nil { + return nil + } + out := new(PolicyStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PolicyTargetReference) DeepCopyInto(out *PolicyTargetReference) { *out = *in diff --git a/apis/v1alpha2/zz_generated.register.go b/apis/v1alpha2/zz_generated.register.go index 5bbf46709a..6183084449 100644 --- a/apis/v1alpha2/zz_generated.register.go +++ b/apis/v1alpha2/zz_generated.register.go @@ -58,6 +58,8 @@ func init() { // Adds the list of known types to Scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, + &BackendTLSPolicy{}, + &BackendTLSPolicyList{}, &GRPCRoute{}, &GRPCRouteList{}, &Gateway{}, diff --git a/apis/v1beta1/httproute_types.go b/apis/v1beta1/httproute_types.go index 34c3abb5de..650f452b73 100644 --- a/apis/v1beta1/httproute_types.go +++ b/apis/v1beta1/httproute_types.go @@ -1162,6 +1162,12 @@ type HTTPBackendRef struct { // * It refers to a Kubernetes Service that has an incompatible appProtocol // for the given Route type // + // * The BackendTLSPolicy object is installed in the cluster, a BackendTLSPolicy + // is present that refers to the Service, and the implementation is unable + // to meet the requirement. At the time of writing, BackendTLSPolicy is + // experimental, but once it becomes standard, this will become a MUST + // requirement. + // // Support: Core for Kubernetes Service // // Support: Implementation-specific for any other resource @@ -1170,6 +1176,8 @@ type HTTPBackendRef struct { // // Support for Kubernetes Service appProtocol: Extended // + // Support for BackendTLSPolicy: Experimental and ImplementationSpecific + // // +optional BackendRef `json:",inline"` diff --git a/apis/v1beta1/object_reference_types.go b/apis/v1beta1/object_reference_types.go index 8ef008db0e..a6524a8910 100644 --- a/apis/v1beta1/object_reference_types.go +++ b/apis/v1beta1/object_reference_types.go @@ -145,3 +145,42 @@ type BackendObjectReference struct { // +optional Port *PortNumber `json:"port,omitempty"` } + +// ObjectReference identifies an API object including its namespace, with no +// default kind. The Group and Kind fields are thus required in this version. +// +// 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 ObjectReference struct { + // Group is the group of the referent. For example, "gateway.networking.k8s.io". + // When set to the empty string, core API group is inferred. + // + // +kubebuilder:validation:Required + Group Group `json:"group"` + + // Kind is the kind of the referent. For example, "ConfigMap". + // + // +kubebuilder:validation:Required + Kind Kind `json:"kind"` + + // Name is the metadata.name of the referenced config map. + // +kubebuilder:validation:Required + Name ObjectName `json:"name"` + + // Namespace is the namespace of the referenced object. When unspecified, the local + // namespace is inferred. + // + // Note that when a namespace different than the local namespace is specified, + // a ReferenceGrant object is required in the referent namespace to allow that + // namespace's owner to accept the reference. See the ReferenceGrant + // documentation for details. + // + // Support: Core + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` +} diff --git a/apis/v1beta1/shared_types.go b/apis/v1beta1/shared_types.go index 3583ad4960..3b814f4202 100644 --- a/apis/v1beta1/shared_types.go +++ b/apis/v1beta1/shared_types.go @@ -262,6 +262,10 @@ type PortNumber int32 // // // +// Note that when the BackendTLSPolicy object is enabled by the implementation, +// there are some extra rules about validity to consider here. See the fields +// where this struct is used for more information about the exact behavior. +// // [KEP-3726]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/3726-standard-application-protocols type BackendRef struct { // BackendObjectReference references a Kubernetes object. diff --git a/apis/v1beta1/zz_generated.deepcopy.go b/apis/v1beta1/zz_generated.deepcopy.go index f7a3c19b91..b1f5a06f31 100644 --- a/apis/v1beta1/zz_generated.deepcopy.go +++ b/apis/v1beta1/zz_generated.deepcopy.go @@ -1035,6 +1035,26 @@ func (in *LocalObjectReference) DeepCopy() *LocalObjectReference { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectReference) DeepCopyInto(out *ObjectReference) { + *out = *in + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(Namespace) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectReference. +func (in *ObjectReference) DeepCopy() *ObjectReference { + if in == nil { + return nil + } + out := new(ObjectReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ParametersReference) DeepCopyInto(out *ParametersReference) { *out = *in diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml new file mode 100644 index 0000000000..d2a0c05f65 --- /dev/null +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -0,0 +1,492 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2245 + gateway.networking.k8s.io/bundle-version: v0.8.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: backendtlspolicies.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: BackendTLSPolicy + listKind: BackendTLSPolicyList + plural: backendtlspolicies + shortNames: + - btlspolicy + singular: backendtlspolicy + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: BackendTLSPolicy provides a way to configure how a Gateway connects + to a Backend via TLS. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of BackendTLSPolicy. + properties: + targetRef: + description: "TargetRef identifies an API object to apply the policy + to. Only Services have Extended support. Implementations MAY support + additional objects, with Implementation Specific support. Note that + this config applies to the entire referenced resource by default, + but this default may change in the future to provide a more granular + application of the policy. \n Support: Extended for Kubernetes Service + \n Support: Implementation-specific for any other resource" + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. When + unspecified, the local namespace is inferred. Even when policy + targets a resource in a different namespace, it MUST only apply + to traffic originating from the same namespace as the policy. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within the + target resource. When unspecified, this targetRef targets the + entire resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name * + Service: Port Name \n If a SectionName is specified, but does + not exist on the targeted object, the Policy must fail to attach, + and the policy implementation should record a `ResolvedRefs` + or similar Condition in the Policy's status." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - group + - kind + - name + type: object + tls: + description: TLS contains backend TLS policy configuration. + properties: + caCertRefs: + description: "CACertRefs contains one or more references to Kubernetes + objects that contain a PEM-encoded TLS CA certificate bundle, + which is used to validate a TLS handshake between the Gateway + and backend Pod. \n If CACertRefs is empty or unspecified, then + StandardCerts must be specified. Only one of CACertRefs or + StandardCerts may be specified, not both. \n If CACertRefs is + empty or unspecified, then system trusted certificates should + be used. If there are none, or the implementation doesn't define + system trusted certificates, then a TLS connection must fail. + \n References to a resource in a different namespace are invalid + for the moment, although we will revisit this in the future. + \n A single CACertRef to a Kubernetes ConfigMap kind has \"Core\" + support. Implementations MAY choose to support attaching multiple + certificates to a backend, but this behavior is implementation-specific. + \n Support: Core - An optional single reference to a Kubernetes + ConfigMap, with the CA certificate in a key named `ca.crt`. + \n Support: Implementation-specific (More than one reference, + or other kinds of resources)." + items: + description: "ObjectReference identifies an API object including + its namespace, with no default kind. The Group and Kind fields + are thus required in this version. \n The API object must + be valid in the cluster; the Group and Kind must be registered + in the cluster for this reference to be valid. \n References + to objects with invalid Group and Kind are not valid, and + must be rejected by the implementation, with appropriate Conditions + set on the containing object." + properties: + group: + description: Group is the group of the referent. For example, + "gateway.networking.k8s.io". When set to the empty string, + core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the referent. For example, + "ConfigMap". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the metadata.name of the referenced + config map. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referenced + object. When unspecified, the local namespace is inferred. + \n Note that when a namespace different than the local + namespace is specified, a ReferenceGrant object is required + in the referent namespace to allow that namespace's owner + to accept the reference. See the ReferenceGrant documentation + for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + type: array + hostname: + description: "Hostname is used for two purposes in the connection + between Gateways and backends: \n 1. Hostname MUST be used as + the SNI to connect to the backend (RFC 6066). 2. Hostname MUST + be used for authentication and MUST match the certificate served + by the matching backend. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + wellKnownCACerts: + description: "WellKnownCACerts specifies whether system CA certificates + may be used in the TLS handshake between the gateway and backend + pod. \n If WellKnownCACerts is unspecified or set to \"\", then + CACertRefs must be specified with at least one entry for a valid + configuration. Only one of CACertRefs or WellKnownCACerts may + be specified, not both. \n WellKnownCACerts must be set to \"System\" + when CACertRefs is unspecified. \n Support: Core for \"System\"" + enum: + - System + type: string + required: + - hostname + type: object + x-kubernetes-validations: + - message: must not contain both CertRefs and StandardCerts + rule: (has(self.caCertRefs) && size(self.caCertRefs) > 0 && has(self.wellKnownCACerts) + && self.wellKnownCACerts != "") + - message: must specify either CertRefs or StandardCerts + rule: '!(has(self.caCertRefs) && size(self.caCertRefs) > 0 || has(self.wellKnownCACerts) + && self.wellKnownCACerts != "")' + required: + - targetRef + - tls + type: object + status: + description: Status defines the current state of BackendTLSPolicy. + properties: + ancestors: + description: "Ancestors is a list of ancestor resources (usually Gateways) + that are associated with the policy, and the status of the policy + with respect to each ancestor. When this policy attaches to a parent, + the controller that manages the parent and the ancestors MUST add + an entry to this list when the controller first sees the policy + and SHOULD update the entry as appropriate when the relevant ancestor + is modified. \n Note that choosing the relevant ancestor is left + to the Policy designers; an important part of Policy design is designing + the right object level at which to namespace this status. \n Note + also that implementations MUST ONLY populate ancestor status for + the Ancestor resources they are responsible for. Implementations + MUST use the ControllerName field to uniquely identify the entries + in this list that they are responsible for. \n Note that to achieve + this, the list of PolicyAncestorStatus structs MUST be treated as + a map with a composite key, made up of the AncestorRef and ControllerName + fields combined. \n A maximum of 16 ancestors will be represented + in this list. An empty list means the Policy is not relevant for + any ancestors. \n If this slice is full, implementations MUST NOT + add further entries." + items: + description: "PolicyAncestorStatus describes the status of a route + with respect to an associated Ancestor. \n Ancestors refer to + objects that are either the Target of a policy or above it in + terms of object hierarchy. For example, if a policy targets a + Service, the Policy's Ancestors are, in order, the Service, the + HTTPRoute, the Gateway, and the GatewayClass. Almost always, in + this hierarchy, the Gateway will be the most useful object to + place Policy status on, so we recommend that implementations SHOULD + use Gateway as the PolicyAncestorStatus object unless the designers + have a _very_ good reason otherwise. \n In the context of policy + attachment, the Ancestor is used to distinguish which resource + results in a distinct application of this policy. For example, + if a policy targets a Service, it may have a distinct result per + attached Gateway. \n Policies targeting the same resource may + have different effects depending on the ancestors of those resources. + For example, different Gateways targeting the same Service may + have different capabilities, especially if they have different + underlying implementations. \n For example, in BackendTLSPolicy, + the Policy attaches to a Service that is used as a backend in + a HTTPRoute that is itself attached to a Gateway. In this case, + the relevant object for status is the Gateway, and that is the + ancestor object referred to in this status. \n Note that a parent + is also an ancestor, so for objects where the parent is the relevant + object for status, this struct SHOULD still be used. \n This struct + is intended to be used in a slice that's effectively a map, with + a composite key made up of the AncestorRef and the ControllerName." + properties: + ancestorRef: + description: AncestorRef corresponds with a ParentRef in the + spec that this PolicyAncestorStatus struct describes the status + of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the + core API group (such as for a \"Service\" kind referent), + Group must be explicitly set to \"\" (empty string). \n + Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are + two kinds of parent resources with \"Core\" support: \n + * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services + only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified, this refers to the local namespace of + the Route. \n Note that there are specific rules for ParentRefs + which cross namespace boundaries. Cross-namespace references + are only valid if they are explicitly allowed by something + in the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides + a generic way to enable any other kind of cross-namespace + reference. \n ParentRefs from a Route to a Service in + the same namespace are \"producer\" routes, which apply + default routing rules to inbound connections from any + namespace to the Service. \n ParentRefs from a Route to + a Service in a different namespace are \"consumer\" routes, + and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for + which the intended destination of the connections are + a Service targeted as a ParentRef of the Route. \n Support: + Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. + It can be interpreted differently based on the type of + parent resource. \n When the parent resource is a Gateway, + this targets all listeners listening on the specified + port that also support this kind of Route(and select this + Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to + a specific port as opposed to a listener(s) whose port(s) + may be changed. When both Port and SectionName are specified, + the name and port of the selected listener must match + both specified values. \n When the parent resource is + a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are + specified, the name and port of the selected port must + match both specified values. \n Implementations MAY choose + to support other parent resources. Implementations supporting + other types of parent resources MUST clearly document + how/if Port is interpreted. \n For the purpose of status, + an attachment is considered successful as long as the + parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them + by Route kind, namespace, or hostname. If 1 of 2 Gateway + listeners accept attachment from the referencing Route, + the Route MUST be considered successfully attached. If + no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name. When both Port (experimental) and SectionName are + specified, the name and port of the selected listener + must match both specified values. * Service: Port Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match + both specified values. Note that attaching Routes to Services + as Parents is part of experimental Mesh support and is + not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this + will reference the entire resource. For the purpose of + status, an attachment is considered successful if at least + one section in the parent resource accepts it. For example, + Gateway listeners can restrict which Routes can attach + to them by Route kind, namespace, or hostname. If 1 of + 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + conditions: + description: Conditions describes the status of the Policy with + respect to the given Ancestor. + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + \n Controllers MUST populate this field when writing status. + Controllers should ensure that entries to status populated + with their ControllerName are cleaned up when they are no + longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + required: + - ancestorRef + - controllerName + type: object + maxItems: 16 + type: array + required: + - ancestors + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index 629c2dd6da..616d4075d2 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -271,7 +271,11 @@ spec: the specified protocol then the backend is considered invalid. Implementations MUST set ResolvedRefs condition to False with the \"UnsupportedProtocol\". \n - \n [KEP-3726]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/3726-standard-application-protocols" + \n Note that when the BackendTLSPolicy object is enabled + by the implementation, there are some extra rules about + validity to consider here. See the fields where this struct + is used for more information about the exact behavior. \n + [KEP-3726]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/3726-standard-application-protocols" properties: group: default: "" diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index d1f4465739..ed8f250598 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -320,7 +320,11 @@ spec: the specified protocol then the backend is considered invalid. Implementations MUST set ResolvedRefs condition to False with the \"UnsupportedProtocol\". \n - \n [KEP-3726]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/3726-standard-application-protocols" + \n Note that when the BackendTLSPolicy object is enabled + by the implementation, there are some extra rules about + validity to consider here. See the fields where this struct + is used for more information about the exact behavior. \n + [KEP-3726]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/3726-standard-application-protocols" properties: group: default: "" diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index 0214120b94..440dca5dd6 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -271,7 +271,11 @@ spec: the specified protocol then the backend is considered invalid. Implementations MUST set ResolvedRefs condition to False with the \"UnsupportedProtocol\". \n - \n [KEP-3726]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/3726-standard-application-protocols" + \n Note that when the BackendTLSPolicy object is enabled + by the implementation, there are some extra rules about + validity to consider here. See the fields where this struct + is used for more information about the exact behavior. \n + [KEP-3726]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/3726-standard-application-protocols" properties: group: default: "" diff --git a/geps/gep-1897.md b/geps/gep-1897.md index 4241ad1009..b9fb00a9cc 100644 --- a/geps/gep-1897.md +++ b/geps/gep-1897.md @@ -1,7 +1,7 @@ # GEP-1897: BackendTLSPolicy - Explicit Backend TLS Connection Configuration * Issue: [#1897](https://github.com/kubernetes-sigs/gateway-api/issues/1897) -* Status: Provisional +* Status: Experimental ## TLDR @@ -213,7 +213,7 @@ StandardCerts is an optional enum that allows users to specify whether to use th Gateway (StandardCerts specfied as "System"), or to use the existing CertRefs (StandardCerts specfied as ""). The use and definition of system certificates is implementation-dependent, and the intent is that these certificates are obtained -from the underlying operating system. CertRefs contains one or more (up to 64) references to Kubernetes objects that +from the underlying operating system. CertRefs contains one or more references to Kubernetes objects that contain PEM-encoded TLS certificates, which are used to establish a TLS handshake between the gateway and backend pod. References to a resource in a different namespace are invalid. If CertRefs is unspecified, then StandardCerts must be set to "System" for a valid configuration. @@ -245,7 +245,7 @@ type BackendTLSPolicy struct { Spec BackendTLSPolicySpec `json:"spec"` // Status defines the current state of BackendTLSPolicy. - Status BackendTLSPolicyStatus `json:"status,omitempty"` + Status PolicyStatus `json:"status,omitempty"` } // BackendTLSPolicySpec defines the desired state of @@ -395,27 +395,6 @@ type ConfigMapObjectReference struct { Namespace *Namespace `json:"namespace,omitempty"` } -// BackendTLSPolicyStatus defines the observed state of BackendTLSPolicy. -type BackendTLSPolicyStatus struct { - // Conditions describe the current conditions of the BackendTLSPolicy. - // - // Implementations should prefer to express BackendTLSPolicy - // conditions using the `BackendTLSPolicyConditionType` and - // `BackendTLSPolicyConditionReason` constants so that - // operators and tools can converge on a common vocabulary to - // describe BackendTLSPolicy state. - // Known condition types are: - // - // * “Accepted” - // - // +optional - // +listType=map - // +listMapKey=type - // +kubebuilder:validation:MaxItems=8 - // +kubebuilder:default={type: "Accepted", status: "Unknown", reason:"Pending", message:"Waiting for validation", lastTransitionTime: "1970-01-01T00:00:00Z"} - Conditions []metav1.Condition `json:"conditions,omitempty"` -} - // BackendTLSPolicyConditionType is the type of a condition used // as a signal by BackendTLSPolicy. This type should be used with // the BackendTLSPolicyStatus.Conditions field. diff --git a/geps/gep-713.md b/geps/gep-713.md index fb48720144..0f1603d6bd 100644 --- a/geps/gep-713.md +++ b/geps/gep-713.md @@ -912,21 +912,31 @@ here. #### Standard status struct -Status: Recommended +Status: Experimental Policy objects SHOULD use the upstream `PolicyAncestorStatus` struct in their respective Status structs. Please see the included `PolicyAncestorStatus` struct, and its use in the `BackendTLSPolicy` object for detailed examples. Included here is a representative version. +This pattern enables different conditions to be set for different "Ancestors" +of the target resource. This is particularly helpful for policies that may be +implemented by multiple controllers or attached to resources with different +capabilities. This pattern also provides a clear view of what resources a +policy is affecting. + +For the best integration with community tooling and consistency across +the broader community, we recommend that all implementations transition +to Policy status with this kind of nested structure. + This is an `Ancestor` status rather than a `Parent` status, as in the Route status because for Policy attachment, the relevant object may or may not be the direct parent. For example, `BackendTLSPolicy` directly attaches to a Service, which may be included -in multiple Routes, in multiple Gateways. However, the status of the `BackendTLSPolicy` -will be different only at the Gateway level, so Gateway is the relevant Ancestor -for the status. +in multiple Routes, in multiple Gateways. However, for many implementations, +the status of the `BackendTLSPolicy` will be different only at the Gateway level, +so Gateway is the relevant Ancestor for the status. Each Gateway that has a Route that includes a backend with an attached `BackendTLSPolicy` MUST have a separate `PolicyAncestorStatus` section in the `BackendTLSPolicy`'s @@ -941,20 +951,26 @@ See [GEP-1897][gep-1897] for the exact details. // PolicyAncestorStatus describes the status of a route with respect to an // associated Ancestor. // -// The object that a Policy attaches to (the object in its TargetRef) is its -// _parent_, and any other objects above it in an object hierarchy are its -// _ancestors_. +// Ancestors refer to objects that are either the Target of a policy or above it in terms +// of object hierarchy. For example, if a policy targets a Service, an Ancestor could be +// a Route or a Gateway. + +// In the context of policy attachment, the Ancestor is used to distinguish which +// resource results in a distinct application of this policy. For example, if a policy +// targets a Service, it may have a distinct result per attached Gateway. // -// For some Policies, particularly Direct Attached Policies, the relevant object -// that distinguishes its status is not necessarily the parent object. +// Policies targeting the same resource may have different effects depending on the +// ancestors of those resources. For example, different Gateways targeting the same +// Service may have different capabilities, especially if they have different underlying +// implementations. // // For example, in BackendTLSPolicy, the Policy attaches to a Service that is // used as a backend in a HTTPRoute that is itself attached to a Gateway. // In this case, the relevant object for status is the Gateway, and that is the // ancestor object referred to in this status. // -// Note that a parent is also an ancestor, so for objects where the parent is the -// relevant object for status, this struct SHOULD still be used. +// Note that a Target of a Policy is also a valid Ancestor, so for objects where +// the Target is the relevant object for status, this struct SHOULD still be used. type PolicyAncestorStatus struct { // AncestorRef corresponds with a ParentRef in the spec that this // RouteParentStatus struct describes the status of. @@ -999,10 +1015,10 @@ type PolicyStatus struct { // an important part of Policy design is designing the right object level at // which to namespace this status. // - // Note also 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 ancestor status for the parent resources they are - // responsible for. + // Note also that implementations MUST ONLY populate ancestor status for + // the Ancestor resources they are responsible for. Implementations MUST + // use the ControllerName field to uniquely identify the entries in this list + // that they are responsible for. // // A maximum of 32 ancestors will be represented in this list. An empty list // means the Policy is not relevant for any ancestors. @@ -1018,6 +1034,10 @@ This is recommended as the base for Policy object's status. As Policy Attachment is a pattern, not an API, "recommended" is the strongest we can make this, but we believe that standardizing this will help a lot with discoverability. +Note that is likely that all Gateway API tooling will expect policy status to follow +this structure. To benefit from broader consistency and discoverability, we +recomment transitioning to this structure for all Gateway API Policies. + #### Standard status Condition on Policy-affected objects Support: Provisional diff --git a/mkdocs.yml b/mkdocs.yml index 30c7ed59e2..7afdc89815 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -94,7 +94,6 @@ nav: - Provisional: - geps/gep-1619.md - geps/gep-1867.md - - geps/gep-1897.md - geps/gep-1911.md - geps/gep-2162.md # - Implementable: @@ -110,6 +109,7 @@ nav: - geps/gep-1709.md - geps/gep-1742.md - geps/gep-1748.md + - geps/gep-1897.md - geps/gep-2257.md - Standard: - geps/gep-709.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 165c88af9f..736b827cf2 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha2/apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/apis_client.go @@ -28,6 +28,7 @@ import ( type GatewayV1alpha2Interface interface { RESTClient() rest.Interface + BackendTLSPoliciesGetter GRPCRoutesGetter GatewaysGetter GatewayClassesGetter @@ -43,6 +44,10 @@ type GatewayV1alpha2Client struct { restClient rest.Interface } +func (c *GatewayV1alpha2Client) BackendTLSPolicies(namespace string) BackendTLSPolicyInterface { + return newBackendTLSPolicies(c, namespace) +} + func (c *GatewayV1alpha2Client) GRPCRoutes(namespace string) GRPCRouteInterface { return newGRPCRoutes(c, namespace) } diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha2/backendtlspolicy.go b/pkg/client/clientset/versioned/typed/apis/v1alpha2/backendtlspolicy.go new file mode 100644 index 0000000000..73b666988f --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/backendtlspolicy.go @@ -0,0 +1,195 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + "context" + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + scheme "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/scheme" +) + +// BackendTLSPoliciesGetter has a method to return a BackendTLSPolicyInterface. +// A group's client should implement this interface. +type BackendTLSPoliciesGetter interface { + BackendTLSPolicies(namespace string) BackendTLSPolicyInterface +} + +// BackendTLSPolicyInterface has methods to work with BackendTLSPolicy resources. +type BackendTLSPolicyInterface interface { + Create(ctx context.Context, backendTLSPolicy *v1alpha2.BackendTLSPolicy, opts v1.CreateOptions) (*v1alpha2.BackendTLSPolicy, error) + Update(ctx context.Context, backendTLSPolicy *v1alpha2.BackendTLSPolicy, opts v1.UpdateOptions) (*v1alpha2.BackendTLSPolicy, error) + UpdateStatus(ctx context.Context, backendTLSPolicy *v1alpha2.BackendTLSPolicy, opts v1.UpdateOptions) (*v1alpha2.BackendTLSPolicy, 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.BackendTLSPolicy, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha2.BackendTLSPolicyList, 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.BackendTLSPolicy, err error) + BackendTLSPolicyExpansion +} + +// backendTLSPolicies implements BackendTLSPolicyInterface +type backendTLSPolicies struct { + client rest.Interface + ns string +} + +// newBackendTLSPolicies returns a BackendTLSPolicies +func newBackendTLSPolicies(c *GatewayV1alpha2Client, namespace string) *backendTLSPolicies { + return &backendTLSPolicies{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the backendTLSPolicy, and returns the corresponding backendTLSPolicy object, and an error if there is any. +func (c *backendTLSPolicies) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.BackendTLSPolicy, err error) { + result = &v1alpha2.BackendTLSPolicy{} + err = c.client.Get(). + Namespace(c.ns). + Resource("backendtlspolicies"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of BackendTLSPolicies that match those selectors. +func (c *backendTLSPolicies) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.BackendTLSPolicyList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha2.BackendTLSPolicyList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("backendtlspolicies"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested backendTLSPolicies. +func (c *backendTLSPolicies) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("backendtlspolicies"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a backendTLSPolicy and creates it. Returns the server's representation of the backendTLSPolicy, and an error, if there is any. +func (c *backendTLSPolicies) Create(ctx context.Context, backendTLSPolicy *v1alpha2.BackendTLSPolicy, opts v1.CreateOptions) (result *v1alpha2.BackendTLSPolicy, err error) { + result = &v1alpha2.BackendTLSPolicy{} + err = c.client.Post(). + Namespace(c.ns). + Resource("backendtlspolicies"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(backendTLSPolicy). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a backendTLSPolicy and updates it. Returns the server's representation of the backendTLSPolicy, and an error, if there is any. +func (c *backendTLSPolicies) Update(ctx context.Context, backendTLSPolicy *v1alpha2.BackendTLSPolicy, opts v1.UpdateOptions) (result *v1alpha2.BackendTLSPolicy, err error) { + result = &v1alpha2.BackendTLSPolicy{} + err = c.client.Put(). + Namespace(c.ns). + Resource("backendtlspolicies"). + Name(backendTLSPolicy.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(backendTLSPolicy). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *backendTLSPolicies) UpdateStatus(ctx context.Context, backendTLSPolicy *v1alpha2.BackendTLSPolicy, opts v1.UpdateOptions) (result *v1alpha2.BackendTLSPolicy, err error) { + result = &v1alpha2.BackendTLSPolicy{} + err = c.client.Put(). + Namespace(c.ns). + Resource("backendtlspolicies"). + Name(backendTLSPolicy.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(backendTLSPolicy). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the backendTLSPolicy and deletes it. Returns an error if one occurs. +func (c *backendTLSPolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("backendtlspolicies"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *backendTLSPolicies) 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("backendtlspolicies"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched backendTLSPolicy. +func (c *backendTLSPolicies) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.BackendTLSPolicy, err error) { + result = &v1alpha2.BackendTLSPolicy{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("backendtlspolicies"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} 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 0f5e66d856..08b78999d2 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_apis_client.go @@ -28,6 +28,10 @@ type FakeGatewayV1alpha2 struct { *testing.Fake } +func (c *FakeGatewayV1alpha2) BackendTLSPolicies(namespace string) v1alpha2.BackendTLSPolicyInterface { + return &FakeBackendTLSPolicies{c, namespace} +} + func (c *FakeGatewayV1alpha2) GRPCRoutes(namespace string) v1alpha2.GRPCRouteInterface { return &FakeGRPCRoutes{c, namespace} } diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_backendtlspolicy.go b/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_backendtlspolicy.go new file mode 100644 index 0000000000..ad40c9e746 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/fake/fake_backendtlspolicy.go @@ -0,0 +1,141 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" +) + +// FakeBackendTLSPolicies implements BackendTLSPolicyInterface +type FakeBackendTLSPolicies struct { + Fake *FakeGatewayV1alpha2 + ns string +} + +var backendtlspoliciesResource = v1alpha2.SchemeGroupVersion.WithResource("backendtlspolicies") + +var backendtlspoliciesKind = v1alpha2.SchemeGroupVersion.WithKind("BackendTLSPolicy") + +// Get takes name of the backendTLSPolicy, and returns the corresponding backendTLSPolicy object, and an error if there is any. +func (c *FakeBackendTLSPolicies) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.BackendTLSPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(backendtlspoliciesResource, c.ns, name), &v1alpha2.BackendTLSPolicy{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.BackendTLSPolicy), err +} + +// List takes label and field selectors, and returns the list of BackendTLSPolicies that match those selectors. +func (c *FakeBackendTLSPolicies) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.BackendTLSPolicyList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(backendtlspoliciesResource, backendtlspoliciesKind, c.ns, opts), &v1alpha2.BackendTLSPolicyList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha2.BackendTLSPolicyList{ListMeta: obj.(*v1alpha2.BackendTLSPolicyList).ListMeta} + for _, item := range obj.(*v1alpha2.BackendTLSPolicyList).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 backendTLSPolicies. +func (c *FakeBackendTLSPolicies) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(backendtlspoliciesResource, c.ns, opts)) + +} + +// Create takes the representation of a backendTLSPolicy and creates it. Returns the server's representation of the backendTLSPolicy, and an error, if there is any. +func (c *FakeBackendTLSPolicies) Create(ctx context.Context, backendTLSPolicy *v1alpha2.BackendTLSPolicy, opts v1.CreateOptions) (result *v1alpha2.BackendTLSPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(backendtlspoliciesResource, c.ns, backendTLSPolicy), &v1alpha2.BackendTLSPolicy{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.BackendTLSPolicy), err +} + +// Update takes the representation of a backendTLSPolicy and updates it. Returns the server's representation of the backendTLSPolicy, and an error, if there is any. +func (c *FakeBackendTLSPolicies) Update(ctx context.Context, backendTLSPolicy *v1alpha2.BackendTLSPolicy, opts v1.UpdateOptions) (result *v1alpha2.BackendTLSPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(backendtlspoliciesResource, c.ns, backendTLSPolicy), &v1alpha2.BackendTLSPolicy{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.BackendTLSPolicy), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeBackendTLSPolicies) UpdateStatus(ctx context.Context, backendTLSPolicy *v1alpha2.BackendTLSPolicy, opts v1.UpdateOptions) (*v1alpha2.BackendTLSPolicy, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(backendtlspoliciesResource, "status", c.ns, backendTLSPolicy), &v1alpha2.BackendTLSPolicy{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.BackendTLSPolicy), err +} + +// Delete takes name of the backendTLSPolicy and deletes it. Returns an error if one occurs. +func (c *FakeBackendTLSPolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(backendtlspoliciesResource, c.ns, name, opts), &v1alpha2.BackendTLSPolicy{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeBackendTLSPolicies) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(backendtlspoliciesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha2.BackendTLSPolicyList{}) + return err +} + +// Patch applies the patch and returns the patched backendTLSPolicy. +func (c *FakeBackendTLSPolicies) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.BackendTLSPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(backendtlspoliciesResource, c.ns, name, pt, data, subresources...), &v1alpha2.BackendTLSPolicy{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.BackendTLSPolicy), 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 6de1bd3e14..d8184bc9c5 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha2/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/generated_expansion.go @@ -18,6 +18,8 @@ limitations under the License. package v1alpha2 +type BackendTLSPolicyExpansion interface{} + type GRPCRouteExpansion interface{} type GatewayExpansion interface{} diff --git a/pkg/client/informers/externalversions/apis/v1alpha2/backendtlspolicy.go b/pkg/client/informers/externalversions/apis/v1alpha2/backendtlspolicy.go new file mode 100644 index 0000000000..2e1ac1aa73 --- /dev/null +++ b/pkg/client/informers/externalversions/apis/v1alpha2/backendtlspolicy.go @@ -0,0 +1,90 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + "context" + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + apisv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + versioned "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned" + internalinterfaces "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/internalinterfaces" + v1alpha2 "sigs.k8s.io/gateway-api/pkg/client/listers/apis/v1alpha2" +) + +// BackendTLSPolicyInformer provides access to a shared informer and lister for +// BackendTLSPolicies. +type BackendTLSPolicyInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha2.BackendTLSPolicyLister +} + +type backendTLSPolicyInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewBackendTLSPolicyInformer constructs a new informer for BackendTLSPolicy 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 NewBackendTLSPolicyInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredBackendTLSPolicyInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredBackendTLSPolicyInformer constructs a new informer for BackendTLSPolicy 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 NewFilteredBackendTLSPolicyInformer(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().BackendTLSPolicies(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().BackendTLSPolicies(namespace).Watch(context.TODO(), options) + }, + }, + &apisv1alpha2.BackendTLSPolicy{}, + resyncPeriod, + indexers, + ) +} + +func (f *backendTLSPolicyInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredBackendTLSPolicyInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *backendTLSPolicyInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apisv1alpha2.BackendTLSPolicy{}, f.defaultInformer) +} + +func (f *backendTLSPolicyInformer) Lister() v1alpha2.BackendTLSPolicyLister { + return v1alpha2.NewBackendTLSPolicyLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/apis/v1alpha2/interface.go b/pkg/client/informers/externalversions/apis/v1alpha2/interface.go index 42a9bfad08..92c95f65f8 100644 --- a/pkg/client/informers/externalversions/apis/v1alpha2/interface.go +++ b/pkg/client/informers/externalversions/apis/v1alpha2/interface.go @@ -24,6 +24,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // BackendTLSPolicies returns a BackendTLSPolicyInformer. + BackendTLSPolicies() BackendTLSPolicyInformer // GRPCRoutes returns a GRPCRouteInformer. GRPCRoutes() GRPCRouteInformer // Gateways returns a GatewayInformer. @@ -53,6 +55,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// BackendTLSPolicies returns a BackendTLSPolicyInformer. +func (v *version) BackendTLSPolicies() BackendTLSPolicyInformer { + return &backendTLSPolicyInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // GRPCRoutes returns a GRPCRouteInformer. func (v *version) GRPCRoutes() GRPCRouteInformer { return &gRPCRouteInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index ddf4bf9296..d45d346642 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -54,6 +54,8 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=gateway.networking.k8s.io, Version=v1alpha2 + case v1alpha2.SchemeGroupVersion.WithResource("backendtlspolicies"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1alpha2().BackendTLSPolicies().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("grpcroutes"): return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1alpha2().GRPCRoutes().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("gateways"): diff --git a/pkg/client/listers/apis/v1alpha2/backendtlspolicy.go b/pkg/client/listers/apis/v1alpha2/backendtlspolicy.go new file mode 100644 index 0000000000..f5927ef190 --- /dev/null +++ b/pkg/client/listers/apis/v1alpha2/backendtlspolicy.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" +) + +// BackendTLSPolicyLister helps list BackendTLSPolicies. +// All objects returned here must be treated as read-only. +type BackendTLSPolicyLister interface { + // List lists all BackendTLSPolicies in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha2.BackendTLSPolicy, err error) + // BackendTLSPolicies returns an object that can list and get BackendTLSPolicies. + BackendTLSPolicies(namespace string) BackendTLSPolicyNamespaceLister + BackendTLSPolicyListerExpansion +} + +// backendTLSPolicyLister implements the BackendTLSPolicyLister interface. +type backendTLSPolicyLister struct { + indexer cache.Indexer +} + +// NewBackendTLSPolicyLister returns a new BackendTLSPolicyLister. +func NewBackendTLSPolicyLister(indexer cache.Indexer) BackendTLSPolicyLister { + return &backendTLSPolicyLister{indexer: indexer} +} + +// List lists all BackendTLSPolicies in the indexer. +func (s *backendTLSPolicyLister) List(selector labels.Selector) (ret []*v1alpha2.BackendTLSPolicy, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.BackendTLSPolicy)) + }) + return ret, err +} + +// BackendTLSPolicies returns an object that can list and get BackendTLSPolicies. +func (s *backendTLSPolicyLister) BackendTLSPolicies(namespace string) BackendTLSPolicyNamespaceLister { + return backendTLSPolicyNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// BackendTLSPolicyNamespaceLister helps list and get BackendTLSPolicies. +// All objects returned here must be treated as read-only. +type BackendTLSPolicyNamespaceLister interface { + // List lists all BackendTLSPolicies in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha2.BackendTLSPolicy, err error) + // Get retrieves the BackendTLSPolicy from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha2.BackendTLSPolicy, error) + BackendTLSPolicyNamespaceListerExpansion +} + +// backendTLSPolicyNamespaceLister implements the BackendTLSPolicyNamespaceLister +// interface. +type backendTLSPolicyNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all BackendTLSPolicies in the indexer for a given namespace. +func (s backendTLSPolicyNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.BackendTLSPolicy, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.BackendTLSPolicy)) + }) + return ret, err +} + +// Get retrieves the BackendTLSPolicy from the indexer for a given namespace and name. +func (s backendTLSPolicyNamespaceLister) Get(name string) (*v1alpha2.BackendTLSPolicy, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha2.Resource("backendtlspolicy"), name) + } + return obj.(*v1alpha2.BackendTLSPolicy), nil +} diff --git a/pkg/client/listers/apis/v1alpha2/expansion_generated.go b/pkg/client/listers/apis/v1alpha2/expansion_generated.go index f41ca73361..b2d81f3385 100644 --- a/pkg/client/listers/apis/v1alpha2/expansion_generated.go +++ b/pkg/client/listers/apis/v1alpha2/expansion_generated.go @@ -18,6 +18,14 @@ limitations under the License. package v1alpha2 +// BackendTLSPolicyListerExpansion allows custom methods to be added to +// BackendTLSPolicyLister. +type BackendTLSPolicyListerExpansion interface{} + +// BackendTLSPolicyNamespaceListerExpansion allows custom methods to be added to +// BackendTLSPolicyNamespaceLister. +type BackendTLSPolicyNamespaceListerExpansion interface{} + // GRPCRouteListerExpansion allows custom methods to be added to // GRPCRouteLister. type GRPCRouteListerExpansion interface{}