From 0f4786536f7482559a517609f940e1f11f65da60 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Thu, 19 Dec 2024 10:34:42 -0800 Subject: [PATCH] Declaratively validate RC.Spec.Replicas optionality The existing test run both declarative and manual validation and it still passes. --- pkg/apis/core/v1/zz_generated.validations.go | 5 +++++ pkg/apis/core/validation/validation.go | 2 +- staging/src/k8s.io/api/core/v1/generated.proto | 1 + staging/src/k8s.io/api/core/v1/types.go | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/apis/core/v1/zz_generated.validations.go b/pkg/apis/core/v1/zz_generated.validations.go index e5aaa2b3882..c5e54847792 100644 --- a/pkg/apis/core/v1/zz_generated.validations.go +++ b/pkg/apis/core/v1/zz_generated.validations.go @@ -89,6 +89,11 @@ func Validate_ReplicationControllerSpec(ctx context.Context, op operation.Operat // field corev1.ReplicationControllerSpec.Replicas errs = append(errs, func(fldPath *field.Path, obj, oldObj *int32) (errs field.ErrorList) { + // optional fields with default values are effectively required + if e := validate.RequiredPointer(ctx, op, fldPath, obj, oldObj); len(e) != 0 { + errs = append(errs, e...) + return // do not proceed + } errs = append(errs, validate.Minimum(ctx, op, fldPath, obj, oldObj, 0)...) return }(fldPath.Child("replicas"), obj.Replicas, safe.Field(oldObj, func(oldObj *corev1.ReplicationControllerSpec) *int32 { return oldObj.Replicas }))...) diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index 8416ec8a074..78abddc1522 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -6322,7 +6322,7 @@ func ValidateReplicationControllerSpec(spec, oldSpec *core.ReplicationController allErrs = append(allErrs, ValidateNonnegativeField(int64(spec.MinReadySeconds), fldPath.Child("minReadySeconds"))...) allErrs = append(allErrs, ValidateNonEmptySelector(spec.Selector, fldPath.Child("selector"))...) if spec.Replicas == nil { - allErrs = append(allErrs, field.Required(fldPath.Child("replicas"), "")) + allErrs = append(allErrs, field.Required(fldPath.Child("replicas"), "").MarkCoveredByDeclarative()) } else { allErrs = append(allErrs, ValidateNonnegativeField(int64(*spec.Replicas), fldPath.Child("replicas")).MarkCoveredByDeclarative()...) } diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index 30353a0bd37..4f5862d2886 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -5085,6 +5085,7 @@ message ReplicationControllerSpec { // Defaults to 1. // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#what-is-a-replicationcontroller // +optional + // +k8s:optional // +default=1 // +k8s:minimum=0 optional int32 replicas = 1; diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index 0da3e37f7b5..e4dc107e665 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -5107,6 +5107,7 @@ type ReplicationControllerSpec struct { // Defaults to 1. // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#what-is-a-replicationcontroller // +optional + // +k8s:optional // +default=1 // +k8s:minimum=0 Replicas *int32 `json:"replicas,omitempty" protobuf:"varint,1,opt,name=replicas"`