@@ -22,11 +22,17 @@ import (
22
22
23
23
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
24
24
25
+ "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel"
26
+ "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/model"
25
27
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"
26
30
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
27
31
"k8s.io/apimachinery/pkg/runtime"
28
32
"k8s.io/apimachinery/pkg/util/validation/field"
29
33
celconfig "k8s.io/apiserver/pkg/apis/cel"
34
+ "k8s.io/apiserver/pkg/cel/common"
35
+ utilfeature "k8s.io/apiserver/pkg/util/feature"
30
36
)
31
37
32
38
type statusStrategy struct {
@@ -94,8 +100,17 @@ func (a statusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Obj
94
100
return field.ErrorList {field .Invalid (field .NewPath ("" ), old , fmt .Sprintf ("has type %T. Must be a pointer to an Unstructured type" , old ))}
95
101
}
96
102
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
+
97
112
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 ... )... )
99
114
100
115
// ratcheting validation of x-kubernetes-list-type value map and set
101
116
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
109
124
if has , err := hasBlockingErr (errs ); has {
110
125
errs = append (errs , err )
111
126
} 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 ... )
113
128
errs = append (errs , err ... )
114
129
}
115
130
}
131
+
132
+ // No-op if not attached to context
133
+ if utilfeature .DefaultFeatureGate .Enabled (apiextensionsfeatures .CRDValidationRatcheting ) {
134
+ validation .Metrics .ObserveRatchetingTime (* correlatedObject .Duration )
135
+ }
116
136
return errs
117
137
}
118
138
0 commit comments