Skip to content

Commit 728a4d2

Browse files
authored
Merge pull request kubernetes#129506 from JoelSpeed/fix-status-ratcheting
Fix CRD status subresource ratcheting
2 parents 35d6959 + aa1d79c commit 728a4d2

File tree

3 files changed

+172
-99
lines changed

3 files changed

+172
-99
lines changed

staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,17 @@ import (
2222

2323
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
2424

25+
"k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel"
26+
"k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/model"
2527
structurallisttype "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/listtype"
28+
"k8s.io/apiextensions-apiserver/pkg/apiserver/validation"
29+
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
2630
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2731
"k8s.io/apimachinery/pkg/runtime"
2832
"k8s.io/apimachinery/pkg/util/validation/field"
2933
celconfig "k8s.io/apiserver/pkg/apis/cel"
34+
"k8s.io/apiserver/pkg/cel/common"
35+
utilfeature "k8s.io/apiserver/pkg/util/feature"
3036
)
3137

3238
type statusStrategy struct {
@@ -94,8 +100,17 @@ func (a statusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Obj
94100
return field.ErrorList{field.Invalid(field.NewPath(""), old, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", old))}
95101
}
96102

103+
var options []validation.ValidationOption
104+
var celOptions []cel.Option
105+
var correlatedObject *common.CorrelatedObject
106+
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CRDValidationRatcheting) {
107+
correlatedObject = common.NewCorrelatedObject(uNew.Object, uOld.Object, &model.Structural{Structural: a.structuralSchema})
108+
options = append(options, validation.WithRatcheting(correlatedObject.Key("status")))
109+
celOptions = append(celOptions, cel.WithRatcheting(correlatedObject))
110+
}
111+
97112
var errs field.ErrorList
98-
errs = append(errs, a.customResourceStrategy.validator.ValidateStatusUpdate(ctx, uNew, uOld, a.scale)...)
113+
errs = append(errs, a.customResourceStrategy.validator.ValidateStatusUpdate(ctx, uNew, uOld, a.scale, options...)...)
99114

100115
// ratcheting validation of x-kubernetes-list-type value map and set
101116
if newErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, uNew.Object); len(newErrs) > 0 {
@@ -109,10 +124,15 @@ func (a statusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Obj
109124
if has, err := hasBlockingErr(errs); has {
110125
errs = append(errs, err)
111126
} else {
112-
err, _ := celValidator.Validate(ctx, nil, a.customResourceStrategy.structuralSchema, uNew.Object, uOld.Object, celconfig.RuntimeCELCostBudget)
127+
err, _ := celValidator.Validate(ctx, nil, a.customResourceStrategy.structuralSchema, uNew.Object, uOld.Object, celconfig.RuntimeCELCostBudget, celOptions...)
113128
errs = append(errs, err...)
114129
}
115130
}
131+
132+
// No-op if not attached to context
133+
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CRDValidationRatcheting) {
134+
validation.Metrics.ObserveRatchetingTime(*correlatedObject.Duration)
135+
}
116136
return errs
117137
}
118138

staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func validateKubeFinalizerName(stringValue string, fldPath *field.Path) []string
9696
return allWarnings
9797
}
9898

99-
func (a customResourceValidator) ValidateStatusUpdate(ctx context.Context, obj, old *unstructured.Unstructured, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList {
99+
func (a customResourceValidator) ValidateStatusUpdate(ctx context.Context, obj, old *unstructured.Unstructured, scale *apiextensions.CustomResourceSubresourceScale, options ...apiextensionsvalidation.ValidationOption) field.ErrorList {
100100
if errs := a.ValidateTypeMeta(ctx, obj); len(errs) > 0 {
101101
return errs
102102
}
@@ -105,7 +105,7 @@ func (a customResourceValidator) ValidateStatusUpdate(ctx context.Context, obj,
105105

106106
allErrs = append(allErrs, validation.ValidateObjectMetaAccessorUpdate(obj, old, field.NewPath("metadata"))...)
107107
if status, hasStatus := obj.UnstructuredContent()["status"]; hasStatus {
108-
allErrs = append(allErrs, apiextensionsvalidation.ValidateCustomResourceUpdate(field.NewPath("status"), status, old.UnstructuredContent()["status"], a.statusSchemaValidator)...)
108+
allErrs = append(allErrs, apiextensionsvalidation.ValidateCustomResourceUpdate(field.NewPath("status"), status, old.UnstructuredContent()["status"], a.statusSchemaValidator, options...)...)
109109
}
110110
allErrs = append(allErrs, a.ValidateScaleStatus(ctx, obj, scale)...)
111111

0 commit comments

Comments
 (0)