diff --git a/apis/v1alpha2/doc.go b/apis/v1alpha2/doc.go index 0fcba7318c..68e1659551 100644 --- a/apis/v1alpha2/doc.go +++ b/apis/v1alpha2/doc.go @@ -16,6 +16,7 @@ limitations under the License. // Package v1alpha2 contains API Schema definitions for the // gateway.networking.k8s.io API group. +// // +kubebuilder:object:generate=true // +groupName=gateway.networking.k8s.io package v1alpha2 diff --git a/apis/v1beta1/doc.go b/apis/v1beta1/doc.go index d29a3c14a2..328100aee8 100644 --- a/apis/v1beta1/doc.go +++ b/apis/v1beta1/doc.go @@ -16,6 +16,7 @@ limitations under the License. // Package v1beta1 contains API Schema definitions for the // gateway.networking.k8s.io API group. +// // +kubebuilder:object:generate=true // +groupName=gateway.networking.k8s.io package v1beta1 diff --git a/apis/v1beta1/gateway_types.go b/apis/v1beta1/gateway_types.go index 2c8548cfac..ad0048e6eb 100644 --- a/apis/v1beta1/gateway_types.go +++ b/apis/v1beta1/gateway_types.go @@ -119,6 +119,12 @@ type GatewaySpec struct { // +kubebuilder:validation:MaxItems=64 Listeners []Listener `json:"listeners"` + // Infrastructure defines infrastructure level attributes about this Gateway instance. + // + // + // +optional + Infrastructure *GatewayInfrastructure `json:"infrastructure,omitempty"` + // Addresses requested for this Gateway. This is optional and behavior can // depend on the implementation. If a value is set in the spec and the // requested address is invalid or unavailable, the implementation MUST @@ -148,6 +154,69 @@ type GatewaySpec struct { Addresses []GatewayAddress `json:"addresses,omitempty"` } +// GatewayInfrastructure defines infrastructure level attributes about a Gateway +type GatewayInfrastructure struct { + // Routability allows the Gateway to specify the accessibility of its addresses. Setting + // this property will override the default value defined by the GatewayClass. + // + // If the desired Gateway routability is incompatible with the GatewayClass implementations + // MUST set the condition `Accepted` to `False` with `Reason` set to `UnsupportedRoutability`. + // + // The default value of routability is implementation specific and MUST remain consistent for + // Gateways with the same gatewayClassName + // + // Implementations MUST clearly document if they support updates to this field. The default + // expectation should be that changes to this field are not supported unless an implementation + // specifies otherwise. + // + // If a Gateway is mutated but does not support the desired routability it MUST set the `Accepted` + // and `Programmed` conditions to `False` with `Reason` set to `UnsupportedRoutability`. + // + // +optional + Routability *GatewayRoutability `json:"routability,omitempty"` +} + +// GatewayRoutablility represents the routability of a Gateway +// +// The pre-defined values listed in this package can be compared semantically. +// `Public` has a larger scope than `Private`, while `Private` has a larger scope than +// `Cluster`. +// +// Implementations can define custom routability values by specifying a vendor +// prefix followed by a slash '/' and a custom name ie. `dev.example.com/my-routability`. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^Public|Private|Cluster|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-_]+$` +type GatewayRoutability string + +const ( + // GatewayRoutabilityPublic means the Gateway's address MUST + // be routable on the public internet. + // + // Support: Extended + GatewayRoutabilityPublic GatewayRoutability = "Public" + + // GatewayRoutabilityPrivate means the Gateway's address MUST + // only be routable inside a private network larger than a single + // cluster (ie. VPC) and MAY include the RFC1918 address space. + // + // It is RECOMMENDED that in-cluster gateways SHOULD NOT support 'Private' routability. + // Kubernetes doesn't have a concept of 'Private' routability for Services. In the future this may + // change upstream. + // + // Support: Extended + GatewayRoutabilityPrivate GatewayRoutability = "Private" + + // GatewayRoutabilityCluster means the Gateway's address MUST + // only be routable inside the [cluster's network]. + // + // Support: Extended + // + // [cluster's network]: https://kubernetes.io/docs/concepts/cluster-administration/networking/#how-to-implement-the-kubernetes-network-model + GatewayRoutabilityCluster GatewayRoutability = "Cluster" +) + // Listener embodies the concept of a logical endpoint where a Gateway accepts // network connections. type Listener struct { @@ -473,6 +542,34 @@ type GatewayAddress struct { Value string `json:"value"` } +// GatewayStatusAddress describes an address that is bound to a Gateway. +type GatewayStatusAddress struct { + // Type of the address. + // + // +optional + // +kubebuilder:default=IPAddress + Type *AddressType `json:"type,omitempty"` + + // Value of the address. The validity of the values will depend + // on the type and support by the controller. + // + // Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Value string `json:"value"` + + // Routability specifies the routable bounds of this address + // Predefined values are: 'Private', 'Public', Cluster + // Other values MUST have a vendor prefix. + // + // Implementations that support Routability MUST populate this field + // + // +optional + // + Routability *GatewayRoutability `json:"routability,omitempty"` +} + // GatewayStatus defines the observed state of Gateway. type GatewayStatus struct { // Addresses lists the IP addresses that have actually been @@ -480,9 +577,17 @@ type GatewayStatus struct { // addresses in the Spec, e.g. if the Gateway automatically // assigns an address from a reserved pool. // + // Implementations that support GatewayRoutability MUST include an address + // that has the same routable semantics as defined in the Gateway spec. + // + // Implementations MAY add additional addresses in status, but they MUST be + // semantically less than the scope of the requested scope. For example if a + // user requests a `Private` routable Gateway then an additional address MAY + // have a routability of `Cluster` but MUST NOT include `Public`. + // // +optional // +kubebuilder:validation:MaxItems=16 - Addresses []GatewayAddress `json:"addresses,omitempty"` + Addresses []GatewayStatusAddress `json:"addresses,omitempty"` // Conditions describe the current conditions of the Gateway. // @@ -572,6 +677,10 @@ const ( // express a range of circumstances, including (but not limited to) IPAM // address exhaustion, address not yet allocated, or a named address not being found. GatewayReasonAddressNotAssigned GatewayConditionReason = "AddressNotAssigned" + + // This reason is used with "Programmed" and "Accepted" conditions when + // desired routability is not able to be fulfilled by the implementation + GatewayUnsupportedRoutability GatewayConditionReason = "UnsupportedRoutability" ) const ( diff --git a/apis/v1beta1/gatewayclass_types.go b/apis/v1beta1/gatewayclass_types.go index f20487bfa5..7a5055a76c 100644 --- a/apis/v1beta1/gatewayclass_types.go +++ b/apis/v1beta1/gatewayclass_types.go @@ -183,6 +183,21 @@ const ( // GatewayClassStatus is the current status for the GatewayClass. type GatewayClassStatus struct { + // Routabilities specifies a list of supported routabilities offered by + // the GatewayClass. The first entry in this list will be the default + // routability used when Gateways of this class are created. + // + // Implementations MAY provide a pre-defined set of GatewayClasses that + // limit the routability choices of a Gateway. + // + // Implementations MUST populate this list with the GatewayRoutability values + // that are supported by this GatewayClass. + // + // +optional + // +kubebuilder:validation:MaxItems=8 + // + Routabilities []GatewayRoutability `json:"routabilities,omitempty"` + // Conditions is the current status from the controller for // this GatewayClass. // diff --git a/apis/v1beta1/zz_generated.deepcopy.go b/apis/v1beta1/zz_generated.deepcopy.go index afda0d4dd2..2f73ce9d1b 100644 --- a/apis/v1beta1/zz_generated.deepcopy.go +++ b/apis/v1beta1/zz_generated.deepcopy.go @@ -265,6 +265,11 @@ func (in *GatewayClassSpec) DeepCopy() *GatewayClassSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GatewayClassStatus) DeepCopyInto(out *GatewayClassStatus) { *out = *in + if in.Routabilities != nil { + in, out := &in.Routabilities, &out.Routabilities + *out = make([]GatewayRoutability, len(*in)) + copy(*out, *in) + } if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make([]v1.Condition, len(*in)) @@ -284,6 +289,26 @@ func (in *GatewayClassStatus) DeepCopy() *GatewayClassStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayInfrastructure) DeepCopyInto(out *GatewayInfrastructure) { + *out = *in + if in.Routability != nil { + in, out := &in.Routability, &out.Routability + *out = new(GatewayRoutability) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayInfrastructure. +func (in *GatewayInfrastructure) DeepCopy() *GatewayInfrastructure { + if in == nil { + return nil + } + out := new(GatewayInfrastructure) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GatewayList) DeepCopyInto(out *GatewayList) { *out = *in @@ -326,6 +351,11 @@ func (in *GatewaySpec) DeepCopyInto(out *GatewaySpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Infrastructure != nil { + in, out := &in.Infrastructure, &out.Infrastructure + *out = new(GatewayInfrastructure) + (*in).DeepCopyInto(*out) + } if in.Addresses != nil { in, out := &in.Addresses, &out.Addresses *out = make([]GatewayAddress, len(*in)) @@ -350,7 +380,7 @@ func (in *GatewayStatus) DeepCopyInto(out *GatewayStatus) { *out = *in if in.Addresses != nil { in, out := &in.Addresses, &out.Addresses - *out = make([]GatewayAddress, len(*in)) + *out = make([]GatewayStatusAddress, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -381,6 +411,31 @@ func (in *GatewayStatus) DeepCopy() *GatewayStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayStatusAddress) DeepCopyInto(out *GatewayStatusAddress) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(AddressType) + **out = **in + } + if in.Routability != nil { + in, out := &in.Routability, &out.Routability + *out = new(GatewayRoutability) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayStatusAddress. +func (in *GatewayStatusAddress) DeepCopy() *GatewayStatusAddress { + if in == nil { + return nil + } + out := new(GatewayStatusAddress) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GatewayTLSConfig) DeepCopyInto(out *GatewayTLSConfig) { *out = *in diff --git a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml index 9f0c7d6d7c..720d5f648f 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml @@ -215,6 +215,27 @@ spec: x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map + routabilities: + description: "Routabilities specifies a list of supported routabilities + offered by the GatewayClass. The first entry in this list will be + the default routability used when Gateways of this class are created. + \n Implementations MAY provide a pre-defined set of GatewayClasses + that limit the routability choices of a Gateway. \n Implementations + MUST populate this list with the GatewayRoutability values that + are supported by this GatewayClass. \n " + items: + description: "GatewayRoutablility represents the routability of + a Gateway \n The pre-defined values listed in this package can + be compared semantically. `Public` has a larger scope than `Private`, + while `Private` has a larger scope than `Cluster`. \n Implementations + can define custom routability values by specifying a vendor prefix + followed by a slash '/' and a custom name ie. `dev.example.com/my-routability`." + maxLength: 253 + minLength: 1 + pattern: ^Public|Private|Cluster|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-_]+$ + type: string + maxItems: 8 + type: array type: object required: - spec @@ -415,6 +436,27 @@ spec: x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map + routabilities: + description: "Routabilities specifies a list of supported routabilities + offered by the GatewayClass. The first entry in this list will be + the default routability used when Gateways of this class are created. + \n Implementations MAY provide a pre-defined set of GatewayClasses + that limit the routability choices of a Gateway. \n Implementations + MUST populate this list with the GatewayRoutability values that + are supported by this GatewayClass. \n " + items: + description: "GatewayRoutablility represents the routability of + a Gateway \n The pre-defined values listed in this package can + be compared semantically. `Public` has a larger scope than `Private`, + while `Private` has a larger scope than `Cluster`. \n Implementations + can define custom routability values by specifying a vendor prefix + followed by a slash '/' and a custom name ie. `dev.example.com/my-routability`." + maxLength: 253 + minLength: 1 + pattern: ^Public|Private|Cluster|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-_]+$ + type: string + maxItems: 8 + type: array type: object required: - spec diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index ddd07e4be6..d57c67524c 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -103,6 +103,30 @@ spec: maxLength: 253 minLength: 1 type: string + infrastructure: + description: "Infrastructure defines infrastructure level attributes + about this Gateway instance. \n " + properties: + routability: + description: "Routability allows the Gateway to specify the accessibility + of its addresses. Setting this property will override the default + value defined by the GatewayClass. \n If the desired Gateway + routability is incompatible with the GatewayClass implementations + MUST set the condition `Accepted` to `False` with `Reason` set + to `UnsupportedRoutability`. \n The default value of routability + is implementation specific and MUST remain consistent for Gateways + with the same gatewayClassName \n Implementations MUST clearly + document if they support updates to this field. The default + expectation should be that changes to this field are not supported + unless an implementation specifies otherwise. \n If a Gateway + is mutated but does not support the desired routability it MUST + set the `Accepted` and `Programmed` conditions to `False` with + `Reason` set to `UnsupportedRoutability`." + maxLength: 253 + minLength: 1 + pattern: ^Public|Private|Cluster|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-_]+$ + type: string + type: object listeners: description: "Listeners associated with this Gateway. Listeners define logical endpoints that are bound on this Gateway's addresses. At @@ -466,14 +490,29 @@ spec: description: Status defines the current state of Gateway. properties: addresses: - description: Addresses lists the IP addresses that have actually been - bound to the Gateway. These addresses may differ from the addresses + description: "Addresses lists the IP addresses that have actually + been bound to the Gateway. These addresses may differ from the addresses in the Spec, e.g. if the Gateway automatically assigns an address - from a reserved pool. + from a reserved pool. \n Implementations that support GatewayRoutability + MUST include an address that has the same routable semantics as + defined in the Gateway spec. \n Implementations MAY add additional + addresses in status, but they MUST be semantically less than the + scope of the requested scope. For example if a user requests a `Private` + routable Gateway then an additional address MAY have a routability + of `Cluster` but MUST NOT include `Public`." items: - description: GatewayAddress describes an address that can be bound + description: GatewayStatusAddress describes an address that is bound to a Gateway. properties: + routability: + description: "Routability specifies the routable bounds of this + address Predefined values are: 'Private', 'Public', Cluster + Other values MUST have a vendor prefix. \n Implementations + that support Routability MUST populate this field \n " + maxLength: 253 + minLength: 1 + pattern: ^Public|Private|Cluster|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-_]+$ + type: string type: default: IPAddress description: Type of the address. @@ -809,6 +848,30 @@ spec: maxLength: 253 minLength: 1 type: string + infrastructure: + description: "Infrastructure defines infrastructure level attributes + about this Gateway instance. \n " + properties: + routability: + description: "Routability allows the Gateway to specify the accessibility + of its addresses. Setting this property will override the default + value defined by the GatewayClass. \n If the desired Gateway + routability is incompatible with the GatewayClass implementations + MUST set the condition `Accepted` to `False` with `Reason` set + to `UnsupportedRoutability`. \n The default value of routability + is implementation specific and MUST remain consistent for Gateways + with the same gatewayClassName \n Implementations MUST clearly + document if they support updates to this field. The default + expectation should be that changes to this field are not supported + unless an implementation specifies otherwise. \n If a Gateway + is mutated but does not support the desired routability it MUST + set the `Accepted` and `Programmed` conditions to `False` with + `Reason` set to `UnsupportedRoutability`." + maxLength: 253 + minLength: 1 + pattern: ^Public|Private|Cluster|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-_]+$ + type: string + type: object listeners: description: "Listeners associated with this Gateway. Listeners define logical endpoints that are bound on this Gateway's addresses. At @@ -1172,14 +1235,29 @@ spec: description: Status defines the current state of Gateway. properties: addresses: - description: Addresses lists the IP addresses that have actually been - bound to the Gateway. These addresses may differ from the addresses + description: "Addresses lists the IP addresses that have actually + been bound to the Gateway. These addresses may differ from the addresses in the Spec, e.g. if the Gateway automatically assigns an address - from a reserved pool. + from a reserved pool. \n Implementations that support GatewayRoutability + MUST include an address that has the same routable semantics as + defined in the Gateway spec. \n Implementations MAY add additional + addresses in status, but they MUST be semantically less than the + scope of the requested scope. For example if a user requests a `Private` + routable Gateway then an additional address MAY have a routability + of `Cluster` but MUST NOT include `Public`." items: - description: GatewayAddress describes an address that can be bound + description: GatewayStatusAddress describes an address that is bound to a Gateway. properties: + routability: + description: "Routability specifies the routable bounds of this + address Predefined values are: 'Private', 'Public', Cluster + Other values MUST have a vendor prefix. \n Implementations + that support Routability MUST populate this field \n " + maxLength: 253 + minLength: 1 + pattern: ^Public|Private|Cluster|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-_]+$ + type: string type: default: IPAddress description: Type of the address. diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index f810b69eb8..48df44fd62 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -466,12 +466,18 @@ spec: description: Status defines the current state of Gateway. properties: addresses: - description: Addresses lists the IP addresses that have actually been - bound to the Gateway. These addresses may differ from the addresses + description: "Addresses lists the IP addresses that have actually + been bound to the Gateway. These addresses may differ from the addresses in the Spec, e.g. if the Gateway automatically assigns an address - from a reserved pool. + from a reserved pool. \n Implementations that support GatewayRoutability + MUST include an address that has the same routable semantics as + defined in the Gateway spec. \n Implementations MAY add additional + addresses in status, but they MUST be semantically less than the + scope of the requested scope. For example if a user requests a `Private` + routable Gateway then an additional address MAY have a routability + of `Cluster` but MUST NOT include `Public`." items: - description: GatewayAddress describes an address that can be bound + description: GatewayStatusAddress describes an address that is bound to a Gateway. properties: type: @@ -1172,12 +1178,18 @@ spec: description: Status defines the current state of Gateway. properties: addresses: - description: Addresses lists the IP addresses that have actually been - bound to the Gateway. These addresses may differ from the addresses + description: "Addresses lists the IP addresses that have actually + been bound to the Gateway. These addresses may differ from the addresses in the Spec, e.g. if the Gateway automatically assigns an address - from a reserved pool. + from a reserved pool. \n Implementations that support GatewayRoutability + MUST include an address that has the same routable semantics as + defined in the Gateway spec. \n Implementations MAY add additional + addresses in status, but they MUST be semantically less than the + scope of the requested scope. For example if a user requests a `Private` + routable Gateway then an additional address MAY have a routability + of `Cluster` but MUST NOT include `Public`." items: - description: GatewayAddress describes an address that can be bound + description: GatewayStatusAddress describes an address that is bound to a Gateway. properties: type: diff --git a/examples/experimental/routability/gateways.yaml b/examples/experimental/routability/gateways.yaml new file mode 100644 index 0000000000..8178015ea4 --- /dev/null +++ b/examples/experimental/routability/gateways.yaml @@ -0,0 +1,38 @@ +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: public-gateway +spec: + gatewayClassName: acme-lb + infrastructure: + routability: Public + listeners: + - name: http + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: private-gateway +spec: + gatewayClassName: acme-lb + infrastructure: + routability: Private + listeners: + - name: http + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: cluster-local-gateway +spec: + gatewayClassName: acme-lb + infrastructure: + routability: Cluster + listeners: + - name: http + protocol: HTTP + port: 80 diff --git a/geps/gep-1651.md b/geps/gep-1651.md index 87c85bb5f9..2d3f3dba7a 100644 --- a/geps/gep-1651.md +++ b/geps/gep-1651.md @@ -1,7 +1,7 @@ # GEP-1651: Gateway Routability * Issue: [#1651](https://github.com/kubernetes-sigs/gateway-api/issues/1651) -* Status: Provisional +* Status: Experimental (See status definitions [here](overview.md#status).) @@ -65,8 +65,7 @@ The default value of `routability` is implementation specific. It is RECOMMENDED the default `routability` remains consistent for Gateways with the same `gatewayClassName`. -Implementations MAY leave the `spec.infrastructure.routability` property unset and instead -signal the default routability using the Gateway's `status.addresses`. See 'Status Addresses` +Implementations MUST signal the default routability using the Gateway's `status.addresses`. See 'Status Addresses` for more details. ### Mutability @@ -85,12 +84,15 @@ MAY choose to leave the old Gateway running with the previous generation's confi // GatewayRoutablility represents the routability of a Gateway // // The pre-defined values listed in this package can be compared semantically. -// [GatewayRoutabilityPublic] has a larger scope than [GatewayRoutabilityPrivate], -// while [GatewayRoutabilityPrivate] has a larger scope than -// [GatewayRoutabilityCluster]. +// `Public` has a larger scope than `Private`, while `Private` has a larger scope than +// `Cluster`. // // Implementations can define custom routability values by specifying a vendor // prefix followed by a slash '/' and a custom name ie. `dev.example.com/my-routability`. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^Public|Private|Cluster|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-_]+$` type GatewayRoutability string const ( @@ -101,14 +103,14 @@ const ( GatewayRoutabilityPublic GatewayRoutability = "Public" // GatewayRoutabilityPrivate means the Gateway's address MUST - // be routable inside a private network larger than a single + // only be routable inside a private network larger than a single // cluster (ie. VPC) and MAY include the RFC1918 address space // // Implementations MAY support this routability GatewayRoutabilityPrivate GatewayRoutability = "Private" // GatewayRoutabilityCluster means the Gateway's address MUST - // be only be routable inside the [cluster's network] + // only be routable inside the [cluster's network] // // Implementations MAY support this routability // @@ -122,23 +124,19 @@ type GatewaySpec struct { // ... } type GatewayInfrastructure struct { - // Routability allows the Gateway to specify the accessibility of it's addresses. Setting - // this property will override the default value defined by the [GatewayClass] + // Routability allows the Gateway to specify the accessibility of its addresses. Setting + // this property will override the default value defined by the GatewayClass. // - // If the desired Gateway routability is incompatible with the [GatewayClass] implementations + // If the desired Gateway routability is incompatible with the GatewayClass implementations // MUST set the condition `Accepted` to `False` with `Reason` set to `UnsupportedRoutability`. - // The default value of routability is implementation specific. - // It is RECOMMENDED that the default routability remains consistent for Gateways with the same - // gatewayClassName - // - // Implementations MAY leave this property unset and signal the default - // routability in the [GatewayStatus] + // The default value of routability is implementation specific and MUST remains consistent for + // Gateways with the same gatewayClassName // // Implementations MAY prevent end-users from updating the routability value of a Gateway. // If updates are allowed the semantics and behaviour will depend on the underlying implementation. - // If a Gateway is mutated but does not support the desired routability it MUST set the conditions - // `Accepted`, `Programmed` to `False` with `Reason` set to `UnsupportedRoutability`. + // If a Gateway is mutated but does not support the desired routability it MUST set `Accepted` + // and `Programmed` conditions to `False` with `Reason` set to `UnsupportedRoutability`. // // It is RECOMMENDED that in-cluster gateways SHOULD NOT support 'Private' routability. // Kubernetes doesn't have a concept of 'Private' routability for Services. In the future this may @@ -159,8 +157,8 @@ type GatewayStatus struct { // // Implementations MAY add additional addresses in status, but they MUST be // semantically less than the scope of the requested scope. For example if a - // user requests a `Cluster` routable Gateway then the list of addresses - // MUST NOT have a routability of `Public` or `Private`. + // user requests a `Private` routable Gateway then an additional address MAY + // have a routability of `Cluster` but MUST NOT include `Public`. // // +optional // +kubebuilder:validation:MaxItems=16 @@ -191,10 +189,12 @@ type GatewayClassStatus struct { // limit the routability choices of a Gateway. // // Implementations that support routability MUST populate this list with - // a subset of the pre-defined [GatewayRoutability] values or vendored + // a subset of the pre-defined GatewayRoutability values or vendored // prefix values. // // +optional + // +kubebuilder:validation:MaxItems=8 + // Routabilities []GatewayRoutability `json:"routabilities"` } ``` diff --git a/hack/invalid-examples/v1beta1/gateway/invalid-routability.yaml b/hack/invalid-examples/v1beta1/gateway/invalid-routability.yaml new file mode 100644 index 0000000000..ad99644dbc --- /dev/null +++ b/hack/invalid-examples/v1beta1/gateway/invalid-routability.yaml @@ -0,0 +1,51 @@ +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: routability-bad-constant +spec: + gatewayClassName: acme-lb + infrastructure: + routability: NotAValidValue + listeners: + - name: http + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: routability-missing-slash-and-suffix +spec: + gatewayClassName: acme-lb + infrastructure: + routability: invalid.prefix.requires.a.slash + listeners: + - name: http + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: routability-missing-suffix +spec: + gatewayClassName: acme-lb + infrastructure: + routability: invalid.prefix.requires.a.slash.and.text/ + listeners: + - name: http + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: routability-vendor-suffix-invalid-character +spec: + gatewayClassName: acme-lb + infrastructure: + routability: some.vendor.prefix/bad!! + listeners: + - name: http + protocol: HTTP + port: 80 diff --git a/hack/verify-examples-kind.sh b/hack/verify-examples-kind.sh index e5d5e9c7c2..4a2eef2f0d 100755 --- a/hack/verify-examples-kind.sh +++ b/hack/verify-examples-kind.sh @@ -49,7 +49,7 @@ trap cleanup INT TERM res=0 # Install kind -(cd $GOPATH && go install sigs.k8s.io/kind@v0.17.0) || res=$? +(cd $GOPATH && go install sigs.k8s.io/kind@v0.20.0) || res=$? # Create cluster KIND_CREATE_ATTEMPTED=true diff --git a/mkdocs.yml b/mkdocs.yml index 5e1412f547..9c0bf0ad9c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -86,7 +86,6 @@ nav: - Provisional: - geps/gep-1324.md - geps/gep-1619.md - - geps/gep-1651.md - geps/gep-1897.md - geps/gep-1867.md - Prototyping: @@ -97,6 +96,7 @@ nav: - geps/gep-1426.md - Experimental: - geps/gep-1748.md + - geps/gep-1651.md - geps/gep-1016.md - geps/gep-957.md - geps/gep-713.md