Add +k8s:supportsSubresource="/scale" for Deployment and ReplicaSet

The declarative validation registration only handled the root "/"
subresource path. When scale subresource operations (PUT/PATCH
.../scale) triggered validation, the generated switch statement
fell through to the InternalError default case, causing
apiserver_validation_declarative_validation_mismatch_total to
increment during e2e tests.

Add the +k8s:supportsSubresource="/scale" tag to Deployment and
ReplicaSet types across apps/v1 and extensions/v1beta1, and update
generated validation files to handle case "/", "/scale":

Signed-off-by: Lidang-Jiang <lidangjiang@gmail.com>
This commit is contained in:
Lidang-Jiang 2026-03-29 14:25:55 +08:00 committed by Lidang Jiang
parent 21a95b5ede
commit 5c40c71a89
6 changed files with 11 additions and 7 deletions

View file

@ -43,7 +43,7 @@ func RegisterValidations(scheme *runtime.Scheme) error {
// type Deployment
scheme.AddValidationFunc((*appsv1.Deployment)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
switch op.Request.SubresourcePath() {
case "/":
case "/", "/scale":
return Validate_Deployment(ctx, op, nil /* fldPath */, obj.(*appsv1.Deployment), safe.Cast[*appsv1.Deployment](oldObj))
}
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
@ -51,7 +51,7 @@ func RegisterValidations(scheme *runtime.Scheme) error {
// type ReplicaSet
scheme.AddValidationFunc((*appsv1.ReplicaSet)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
switch op.Request.SubresourcePath() {
case "/":
case "/", "/scale":
return Validate_ReplicaSet(ctx, op, nil /* fldPath */, obj.(*appsv1.ReplicaSet), safe.Cast[*appsv1.ReplicaSet](oldObj))
}
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}

View file

@ -43,7 +43,7 @@ func RegisterValidations(scheme *runtime.Scheme) error {
// type Deployment
scheme.AddValidationFunc((*appsv1beta1.Deployment)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
switch op.Request.SubresourcePath() {
case "/":
case "/", "/scale":
return Validate_Deployment(ctx, op, nil /* fldPath */, obj.(*appsv1beta1.Deployment), safe.Cast[*appsv1beta1.Deployment](oldObj))
}
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}

View file

@ -43,7 +43,7 @@ func RegisterValidations(scheme *runtime.Scheme) error {
// type Deployment
scheme.AddValidationFunc((*appsv1beta2.Deployment)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
switch op.Request.SubresourcePath() {
case "/":
case "/", "/scale":
return Validate_Deployment(ctx, op, nil /* fldPath */, obj.(*appsv1beta2.Deployment), safe.Cast[*appsv1beta2.Deployment](oldObj))
}
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
@ -51,7 +51,7 @@ func RegisterValidations(scheme *runtime.Scheme) error {
// type ReplicaSet
scheme.AddValidationFunc((*appsv1beta2.ReplicaSet)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
switch op.Request.SubresourcePath() {
case "/":
case "/", "/scale":
return Validate_ReplicaSet(ctx, op, nil /* fldPath */, obj.(*appsv1beta2.ReplicaSet), safe.Cast[*appsv1beta2.ReplicaSet](oldObj))
}
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}

View file

@ -367,6 +367,7 @@ type StatefulSetList struct {
// +genclient:method=ApplyScale,verb=apply,subresource=scale,input=k8s.io/api/autoscaling/v1.Scale,result=k8s.io/api/autoscaling/v1.Scale
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:prerelease-lifecycle-gen:introduced=1.9
// +k8s:supportsSubresource="/scale"
// Deployment enables declarative updates for Pods and ReplicaSets.
// +k8s:supportsSubresource="/status"
@ -838,6 +839,7 @@ type DaemonSetList struct {
// +genclient:method=ApplyScale,verb=apply,subresource=scale,input=k8s.io/api/autoscaling/v1.Scale,result=k8s.io/api/autoscaling/v1.Scale
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:prerelease-lifecycle-gen:introduced=1.9
// +k8s:supportsSubresource="/scale"
// ReplicaSet ensures that a specified number of pod replicas are running at any given time.
// +k8s:supportsSubresource="/status"

View file

@ -84,6 +84,7 @@ type Scale struct {
// +k8s:prerelease-lifecycle-gen:deprecated=1.8
// +k8s:prerelease-lifecycle-gen:removed=1.16
// +k8s:prerelease-lifecycle-gen:replacement=apps,v1,Deployment
// +k8s:supportsSubresource="/scale"
// DEPRECATED - This group version of Deployment is deprecated by apps/v1beta2/Deployment. See the release notes for
// more information.
@ -915,6 +916,7 @@ type IngressBackend struct {
// +k8s:prerelease-lifecycle-gen:deprecated=1.8
// +k8s:prerelease-lifecycle-gen:removed=1.16
// +k8s:prerelease-lifecycle-gen:replacement=apps,v1,ReplicaSet
// +k8s:supportsSubresource="/scale"
// DEPRECATED - This group version of ReplicaSet is deprecated by apps/v1beta2/ReplicaSet. See the release notes for
// more information.

View file

@ -42,7 +42,7 @@ func RegisterValidations(scheme *runtime.Scheme) error {
// type Deployment
scheme.AddValidationFunc((*Deployment)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
switch op.Request.SubresourcePath() {
case "/":
case "/", "/scale":
return Validate_Deployment(ctx, op, nil /* fldPath */, obj.(*Deployment), safe.Cast[*Deployment](oldObj))
}
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}
@ -58,7 +58,7 @@ func RegisterValidations(scheme *runtime.Scheme) error {
// type ReplicaSet
scheme.AddValidationFunc((*ReplicaSet)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList {
switch op.Request.SubresourcePath() {
case "/":
case "/", "/scale":
return Validate_ReplicaSet(ctx, op, nil /* fldPath */, obj.(*ReplicaSet), safe.Cast[*ReplicaSet](oldObj))
}
return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))}