|
|
@@ -45,29 +45,25 @@ import (
|
|
|
|
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
|
|
|
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// customResourceStrategy implements behavior for CustomResources.
|
|
|
|
// customResourceStrategy implements behavior for CustomResources for a single
|
|
|
|
|
|
|
|
// version
|
|
|
|
type customResourceStrategy struct {
|
|
|
|
type customResourceStrategy struct {
|
|
|
|
runtime.ObjectTyper
|
|
|
|
runtime.ObjectTyper
|
|
|
|
names.NameGenerator
|
|
|
|
names.NameGenerator
|
|
|
|
|
|
|
|
|
|
|
|
namespaceScoped bool
|
|
|
|
namespaceScoped bool
|
|
|
|
validator customResourceValidator
|
|
|
|
validator customResourceValidator
|
|
|
|
structuralSchemas map[string]*structuralschema.Structural
|
|
|
|
structuralSchema *structuralschema.Structural
|
|
|
|
celValidators map[string]*cel.Validator
|
|
|
|
celValidator *cel.Validator
|
|
|
|
status *apiextensions.CustomResourceSubresourceStatus
|
|
|
|
status *apiextensions.CustomResourceSubresourceStatus
|
|
|
|
scale *apiextensions.CustomResourceSubresourceScale
|
|
|
|
scale *apiextensions.CustomResourceSubresourceScale
|
|
|
|
kind schema.GroupVersionKind
|
|
|
|
kind schema.GroupVersionKind
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func NewStrategy(typer runtime.ObjectTyper, namespaceScoped bool, kind schema.GroupVersionKind, schemaValidator, statusSchemaValidator validation.SchemaValidator, structuralSchemas map[string]*structuralschema.Structural, status *apiextensions.CustomResourceSubresourceStatus, scale *apiextensions.CustomResourceSubresourceScale) customResourceStrategy {
|
|
|
|
func NewStrategy(typer runtime.ObjectTyper, namespaceScoped bool, kind schema.GroupVersionKind, schemaValidator, statusSchemaValidator validation.SchemaValidator, structuralSchema *structuralschema.Structural, status *apiextensions.CustomResourceSubresourceStatus, scale *apiextensions.CustomResourceSubresourceScale) customResourceStrategy {
|
|
|
|
celValidators := map[string]*cel.Validator{}
|
|
|
|
var celValidator *cel.Validator
|
|
|
|
if utilfeature.DefaultFeatureGate.Enabled(features.CustomResourceValidationExpressions) {
|
|
|
|
if utilfeature.DefaultFeatureGate.Enabled(features.CustomResourceValidationExpressions) {
|
|
|
|
for name, s := range structuralSchemas {
|
|
|
|
celValidator = cel.NewValidator(structuralSchema, true, celconfig.PerCallLimit) // CEL programs are compiled and cached here
|
|
|
|
v := cel.NewValidator(s, true, celconfig.PerCallLimit) // CEL programs are compiled and cached here
|
|
|
|
|
|
|
|
if v != nil {
|
|
|
|
|
|
|
|
celValidators[name] = v
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return customResourceStrategy{
|
|
|
|
return customResourceStrategy{
|
|
|
@@ -82,8 +78,8 @@ func NewStrategy(typer runtime.ObjectTyper, namespaceScoped bool, kind schema.Gr
|
|
|
|
schemaValidator: schemaValidator,
|
|
|
|
schemaValidator: schemaValidator,
|
|
|
|
statusSchemaValidator: statusSchemaValidator,
|
|
|
|
statusSchemaValidator: statusSchemaValidator,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
structuralSchemas: structuralSchemas,
|
|
|
|
structuralSchema: structuralSchema,
|
|
|
|
celValidators: celValidators,
|
|
|
|
celValidator: celValidator,
|
|
|
|
kind: kind,
|
|
|
|
kind: kind,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -173,18 +169,17 @@ func (a customResourceStrategy) Validate(ctx context.Context, obj runtime.Object
|
|
|
|
errs = append(errs, a.validator.Validate(ctx, u, a.scale)...)
|
|
|
|
errs = append(errs, a.validator.Validate(ctx, u, a.scale)...)
|
|
|
|
|
|
|
|
|
|
|
|
// validate embedded resources
|
|
|
|
// validate embedded resources
|
|
|
|
v := obj.GetObjectKind().GroupVersionKind().Version
|
|
|
|
errs = append(errs, schemaobjectmeta.Validate(nil, u.Object, a.structuralSchema, false)...)
|
|
|
|
errs = append(errs, schemaobjectmeta.Validate(nil, u.Object, a.structuralSchemas[v], false)...)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// validate x-kubernetes-list-type "map" and "set" invariant
|
|
|
|
// validate x-kubernetes-list-type "map" and "set" invariant
|
|
|
|
errs = append(errs, structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchemas[v], u.Object)...)
|
|
|
|
errs = append(errs, structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, u.Object)...)
|
|
|
|
|
|
|
|
|
|
|
|
// validate x-kubernetes-validations rules
|
|
|
|
// validate x-kubernetes-validations rules
|
|
|
|
if celValidator, ok := a.celValidators[v]; ok {
|
|
|
|
if celValidator := a.celValidator; celValidator != nil {
|
|
|
|
if has, err := hasBlockingErr(errs); has {
|
|
|
|
if has, err := hasBlockingErr(errs); has {
|
|
|
|
errs = append(errs, err)
|
|
|
|
errs = append(errs, err)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
err, _ := celValidator.Validate(ctx, nil, a.structuralSchemas[v], u.Object, nil, celconfig.RuntimeCELCostBudget)
|
|
|
|
err, _ := celValidator.Validate(ctx, nil, a.structuralSchema, u.Object, nil, celconfig.RuntimeCELCostBudget)
|
|
|
|
errs = append(errs, err...)
|
|
|
|
errs = append(errs, err...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -251,20 +246,19 @@ func (a customResourceStrategy) ValidateUpdate(ctx context.Context, obj, old run
|
|
|
|
errs = append(errs, a.validator.ValidateUpdate(ctx, uNew, uOld, a.scale)...)
|
|
|
|
errs = append(errs, a.validator.ValidateUpdate(ctx, uNew, uOld, a.scale)...)
|
|
|
|
|
|
|
|
|
|
|
|
// Checks the embedded objects. We don't make a difference between update and create for those.
|
|
|
|
// Checks the embedded objects. We don't make a difference between update and create for those.
|
|
|
|
v := obj.GetObjectKind().GroupVersionKind().Version
|
|
|
|
errs = append(errs, schemaobjectmeta.Validate(nil, uNew.Object, a.structuralSchema, false)...)
|
|
|
|
errs = append(errs, schemaobjectmeta.Validate(nil, uNew.Object, a.structuralSchemas[v], false)...)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ratcheting validation of x-kubernetes-list-type value map and set
|
|
|
|
// ratcheting validation of x-kubernetes-list-type value map and set
|
|
|
|
if oldErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchemas[v], uOld.Object); len(oldErrs) == 0 {
|
|
|
|
if oldErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, uOld.Object); len(oldErrs) == 0 {
|
|
|
|
errs = append(errs, structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchemas[v], uNew.Object)...)
|
|
|
|
errs = append(errs, structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, uNew.Object)...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// validate x-kubernetes-validations rules
|
|
|
|
// validate x-kubernetes-validations rules
|
|
|
|
if celValidator, ok := a.celValidators[v]; ok {
|
|
|
|
if celValidator := a.celValidator; celValidator != nil {
|
|
|
|
if has, err := hasBlockingErr(errs); has {
|
|
|
|
if has, err := hasBlockingErr(errs); has {
|
|
|
|
errs = append(errs, err)
|
|
|
|
errs = append(errs, err)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
err, _ := celValidator.Validate(ctx, nil, a.structuralSchemas[v], uNew.Object, uOld.Object, celconfig.RuntimeCELCostBudget)
|
|
|
|
err, _ := celValidator.Validate(ctx, nil, a.structuralSchema, uNew.Object, uOld.Object, celconfig.RuntimeCELCostBudget)
|
|
|
|
errs = append(errs, err...)
|
|
|
|
errs = append(errs, err...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|