diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index 3e1ec4c7ea..febde8c7bc 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -390,6 +390,9 @@ type Listener struct { // same port, subject to the Listener compatibility rules. // // Support: Core + // + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 Port PortNumber `json:"port"` // Protocol specifies the network protocol this listener expects to receive. diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go index 6131d70b7b..21304aa518 100644 --- a/apis/v1/httproute_types.go +++ b/apis/v1/httproute_types.go @@ -1209,6 +1209,9 @@ type HTTPRequestRedirectFilter struct { // Support: Extended // // +optional + // + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 Port *PortNumber `json:"port,omitempty"` // StatusCode is the HTTP status code to be used in response. diff --git a/apis/v1/object_reference_types.go b/apis/v1/object_reference_types.go index dd507b2136..0b254b367e 100644 --- a/apis/v1/object_reference_types.go +++ b/apis/v1/object_reference_types.go @@ -143,6 +143,8 @@ type BackendObjectReference struct { // resource or this field. // // +optional + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 Port *PortNumber `json:"port,omitempty"` } diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index e059b98145..586eb916b8 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -148,6 +148,9 @@ type ParentReference struct { // Support: Extended // // +optional + // + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 Port *PortNumber `json:"port,omitempty"` } @@ -227,9 +230,6 @@ type CommonRouteSpec struct { } // PortNumber defines a network port. -// -// +kubebuilder:validation:Minimum=1 -// +kubebuilder:validation:Maximum=65535 type PortNumber int32 // BackendRef defines how a Route should forward a request to a Kubernetes diff --git a/apis/v1alpha2/shared_types.go b/apis/v1alpha2/shared_types.go index 2fb84d5f3b..3d2f787909 100644 --- a/apis/v1alpha2/shared_types.go +++ b/apis/v1alpha2/shared_types.go @@ -40,9 +40,6 @@ type ParentReference = v1.ParentReference type CommonRouteSpec = v1.CommonRouteSpec // PortNumber defines a network port. -// -// +kubebuilder:validation:Minimum=1 -// +kubebuilder:validation:Maximum=65535 type PortNumber = v1.PortNumber // BackendRef defines how a Route should forward a request to a Kubernetes diff --git a/apis/v1beta1/shared_types.go b/apis/v1beta1/shared_types.go index 3dbcc280fc..ce1c430649 100644 --- a/apis/v1beta1/shared_types.go +++ b/apis/v1beta1/shared_types.go @@ -40,9 +40,6 @@ type ParentReference = v1.ParentReference type CommonRouteSpec = v1.CommonRouteSpec // PortNumber defines a network port. -// -// +kubebuilder:validation:Minimum=1 -// +kubebuilder:validation:Maximum=65535 type PortNumber = v1.PortNumber // BackendRef defines how a Route should forward a request to a Kubernetes diff --git a/apisx/v1alpha1/xlistenerset_types.go b/apisx/v1alpha1/xlistenerset_types.go index 529b7f3508..37df1f776d 100644 --- a/apisx/v1alpha1/xlistenerset_types.go +++ b/apisx/v1alpha1/xlistenerset_types.go @@ -127,7 +127,13 @@ type ListenerEntry struct { // Port is the network port. Multiple listeners may use the // same port, subject to the Listener compatibility rules. - Port PortNumber `json:"port"` + // + // +optional + // + // +kubebuilder:default=0 + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=65535 + Port PortNumber `json:"port,omitempty"` // Protocol specifies the network protocol this listener expects to receive. Protocol ProtocolType `json:"protocol"` @@ -208,6 +214,9 @@ type ListenerEntryStatus struct { Name SectionName `json:"name"` // Port is the network port the listener is configured to listen on. + // + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 Port PortNumber `json:"port"` // SupportedKinds is the list indicating the Kinds supported by this diff --git a/applyconfiguration/internal/internal.go b/applyconfiguration/internal/internal.go index 7a69ee3876..58971ef5e2 100644 --- a/applyconfiguration/internal/internal.go +++ b/applyconfiguration/internal/internal.go @@ -1753,7 +1753,6 @@ var schemaYAML = typed.YAMLObject(`types: - name: port type: scalar: numeric - default: 0 - name: protocol type: scalar: string diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml index d370a07373..9f03354693 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml @@ -271,12 +271,13 @@ spec: pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string port: + default: 0 description: |- Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. format: int32 maximum: 65535 - minimum: 1 + minimum: 0 type: integer protocol: description: Protocol specifies the network protocol this listener @@ -514,7 +515,6 @@ spec: > 0 || size(self.options) > 0 : true' required: - name - - port - protocol type: object maxItems: 64 diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 1516450f27..9279b1767a 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -7748,7 +7748,6 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_ListenerEntry(ref common.Refere "port": { SchemaProps: spec.SchemaProps{ Description: "Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules.", - Default: 0, Type: []string{"integer"}, Format: "int32", }, @@ -7774,7 +7773,7 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_ListenerEntry(ref common.Refere }, }, }, - Required: []string{"name", "port", "protocol"}, + Required: []string{"name", "protocol"}, }, }, Dependencies: []string{ diff --git a/pkg/generator/main.go b/pkg/generator/main.go index dc170b8823..1149e1a902 100644 --- a/pkg/generator/main.go +++ b/pkg/generator/main.go @@ -69,6 +69,8 @@ func main() { log.Fatalf("failed to register markers: %s", err) } + registerMarkerOverrides(parser.Collector.Registry) + crd.AddKnownTypes(parser) for _, r := range roots { parser.NeedPackage(r) diff --git a/pkg/generator/markers.go b/pkg/generator/markers.go new file mode 100644 index 0000000000..ab5f625aae --- /dev/null +++ b/pkg/generator/markers.go @@ -0,0 +1,66 @@ +/* +Copyright 2025 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 main + +import ( + apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "sigs.k8s.io/controller-tools/pkg/markers" +) + +type Minimum float64 + +func (m Minimum) Value() float64 { + return float64(m) +} + +//nolint:unparam +func (m Minimum) ApplyToSchema(schema *apiext.JSONSchemaProps) error { + val := m.Value() + schema.Minimum = &val + return nil +} + +type Maximum float64 + +func (m Maximum) Value() float64 { + return float64(m) +} + +//nolint:unparam +func (m Maximum) ApplyToSchema(schema *apiext.JSONSchemaProps) error { + val := m.Value() + schema.Maximum = &val + return nil +} + +// kubebuilder Min Max markers are broken with type aliases +func registerMarkerOverrides(into *markers.Registry) { + minMarker, _ := markers.MakeDefinition( + "kubebuilder:validation:Minimum", + markers.DescribesField, + Minimum(0), + ) + + maxMarker, _ := markers.MakeDefinition( + "kubebuilder:validation:Maximum", + markers.DescribesField, + Maximum(0), + ) + + into.Register(minMarker) //nolint:errcheck + into.Register(maxMarker) //nolint:errcheck +}