diff --git a/pkg/apis/flowcontrol/v1/zz_generated.validations.go b/pkg/apis/flowcontrol/v1/zz_generated.validations.go index 73e28035dba..6963dadcb95 100644 --- a/pkg/apis/flowcontrol/v1/zz_generated.validations.go +++ b/pkg/apis/flowcontrol/v1/zz_generated.validations.go @@ -22,7 +22,16 @@ limitations under the License. package v1 import ( + context "context" + fmt "fmt" + + flowcontrolv1 "k8s.io/api/flowcontrol/v1" + equality "k8s.io/apimachinery/pkg/api/equality" + operation "k8s.io/apimachinery/pkg/api/operation" + safe "k8s.io/apimachinery/pkg/api/safe" + validate "k8s.io/apimachinery/pkg/api/validate" runtime "k8s.io/apimachinery/pkg/runtime" + field "k8s.io/apimachinery/pkg/util/validation/field" ) func init() { localSchemeBuilder.Register(RegisterValidations) } @@ -30,5 +39,182 @@ func init() { localSchemeBuilder.Register(RegisterValidations) } // RegisterValidations adds validation functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterValidations(scheme *runtime.Scheme) error { + // type PriorityLevelConfiguration + scheme.AddValidationFunc((*flowcontrolv1.PriorityLevelConfiguration)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList { + switch op.Request.SubresourcePath() { + case "/": + return Validate_PriorityLevelConfiguration(ctx, op, nil /* fldPath */, obj.(*flowcontrolv1.PriorityLevelConfiguration), safe.Cast[*flowcontrolv1.PriorityLevelConfiguration](oldObj)) + } + return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))} + }) return nil } + +// Validate_PriorityLevelConfiguration validates an instance of PriorityLevelConfiguration according +// to declarative validation rules in the API schema. +func Validate_PriorityLevelConfiguration(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1.PriorityLevelConfiguration) (errs field.ErrorList) { + // field flowcontrolv1.PriorityLevelConfiguration.TypeMeta has no validation + // field flowcontrolv1.PriorityLevelConfiguration.ObjectMeta has no validation + + // field flowcontrolv1.PriorityLevelConfiguration.Spec + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1.PriorityLevelConfigurationSpec, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + // call the type's validation function + errs = append(errs, Validate_PriorityLevelConfigurationSpec(ctx, op, fldPath, obj, oldObj)...) + return + }(fldPath.Child("spec"), &obj.Spec, safe.Field(oldObj, func(oldObj *flowcontrolv1.PriorityLevelConfiguration) *flowcontrolv1.PriorityLevelConfigurationSpec { + return &oldObj.Spec + }), oldObj != nil)...) + + // field flowcontrolv1.PriorityLevelConfiguration.Status has no validation + return errs +} + +// Validate_PriorityLevelConfigurationSpec validates an instance of PriorityLevelConfigurationSpec according +// to declarative validation rules in the API schema. +func Validate_PriorityLevelConfigurationSpec(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1.PriorityLevelConfigurationSpec) (errs field.ErrorList) { + errs = append(errs, validate.Discriminated(ctx, op, fldPath, obj, oldObj, "exempt", func(obj *flowcontrolv1.PriorityLevelConfigurationSpec) *flowcontrolv1.ExemptPriorityLevelConfiguration { + return obj.Exempt + }, func(obj *flowcontrolv1.PriorityLevelConfigurationSpec) flowcontrolv1.PriorityLevelEnablement { + return obj.Type + }, validate.SemanticDeepEqual, func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1.ExemptPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + errs = append(errs, validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha()...) + return errs + }, []validate.DiscriminatedRule[*flowcontrolv1.ExemptPriorityLevelConfiguration, flowcontrolv1.PriorityLevelEnablement]{ + { + Value: "Exempt", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1.ExemptPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + { + Value: "Limited", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1.ExemptPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + })...) + errs = append(errs, validate.Discriminated(ctx, op, fldPath, obj, oldObj, "limited", func(obj *flowcontrolv1.PriorityLevelConfigurationSpec) *flowcontrolv1.LimitedPriorityLevelConfiguration { + return obj.Limited + }, func(obj *flowcontrolv1.PriorityLevelConfigurationSpec) flowcontrolv1.PriorityLevelEnablement { + return obj.Type + }, validate.SemanticDeepEqual, func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1.LimitedPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + errs = append(errs, validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha()...) + return errs + }, []validate.DiscriminatedRule[*flowcontrolv1.LimitedPriorityLevelConfiguration, flowcontrolv1.PriorityLevelEnablement]{ + { + Value: "Exempt", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1.LimitedPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + { + Value: "Limited", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1.LimitedPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.RequiredPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + })...) + + // field flowcontrolv1.PriorityLevelConfigurationSpec.Type + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1.PriorityLevelEnablement, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) { + return nil + } + // call field-attached validations + earlyReturn := false + if e := validate.RequiredValue(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + }(fldPath.Child("type"), &obj.Type, safe.Field(oldObj, func(oldObj *flowcontrolv1.PriorityLevelConfigurationSpec) *flowcontrolv1.PriorityLevelEnablement { + return &oldObj.Type + }), oldObj != nil)...) + + // field flowcontrolv1.PriorityLevelConfigurationSpec.Limited + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1.LimitedPriorityLevelConfiguration, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + }(fldPath.Child("limited"), obj.Limited, safe.Field(oldObj, func(oldObj *flowcontrolv1.PriorityLevelConfigurationSpec) *flowcontrolv1.LimitedPriorityLevelConfiguration { + return oldObj.Limited + }), oldObj != nil)...) + + // field flowcontrolv1.PriorityLevelConfigurationSpec.Exempt + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1.ExemptPriorityLevelConfiguration, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + }(fldPath.Child("exempt"), obj.Exempt, safe.Field(oldObj, func(oldObj *flowcontrolv1.PriorityLevelConfigurationSpec) *flowcontrolv1.ExemptPriorityLevelConfiguration { + return oldObj.Exempt + }), oldObj != nil)...) + + return errs +} diff --git a/pkg/apis/flowcontrol/v1beta1/zz_generated.validations.go b/pkg/apis/flowcontrol/v1beta1/zz_generated.validations.go index 0b9e874b635..6a6cf919051 100644 --- a/pkg/apis/flowcontrol/v1beta1/zz_generated.validations.go +++ b/pkg/apis/flowcontrol/v1beta1/zz_generated.validations.go @@ -22,7 +22,16 @@ limitations under the License. package v1beta1 import ( + context "context" + fmt "fmt" + + flowcontrolv1beta1 "k8s.io/api/flowcontrol/v1beta1" + equality "k8s.io/apimachinery/pkg/api/equality" + operation "k8s.io/apimachinery/pkg/api/operation" + safe "k8s.io/apimachinery/pkg/api/safe" + validate "k8s.io/apimachinery/pkg/api/validate" runtime "k8s.io/apimachinery/pkg/runtime" + field "k8s.io/apimachinery/pkg/util/validation/field" ) func init() { localSchemeBuilder.Register(RegisterValidations) } @@ -30,5 +39,182 @@ func init() { localSchemeBuilder.Register(RegisterValidations) } // RegisterValidations adds validation functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterValidations(scheme *runtime.Scheme) error { + // type PriorityLevelConfiguration + scheme.AddValidationFunc((*flowcontrolv1beta1.PriorityLevelConfiguration)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList { + switch op.Request.SubresourcePath() { + case "/": + return Validate_PriorityLevelConfiguration(ctx, op, nil /* fldPath */, obj.(*flowcontrolv1beta1.PriorityLevelConfiguration), safe.Cast[*flowcontrolv1beta1.PriorityLevelConfiguration](oldObj)) + } + return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))} + }) return nil } + +// Validate_PriorityLevelConfiguration validates an instance of PriorityLevelConfiguration according +// to declarative validation rules in the API schema. +func Validate_PriorityLevelConfiguration(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta1.PriorityLevelConfiguration) (errs field.ErrorList) { + // field flowcontrolv1beta1.PriorityLevelConfiguration.TypeMeta has no validation + // field flowcontrolv1beta1.PriorityLevelConfiguration.ObjectMeta has no validation + + // field flowcontrolv1beta1.PriorityLevelConfiguration.Spec + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1beta1.PriorityLevelConfigurationSpec, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + // call the type's validation function + errs = append(errs, Validate_PriorityLevelConfigurationSpec(ctx, op, fldPath, obj, oldObj)...) + return + }(fldPath.Child("spec"), &obj.Spec, safe.Field(oldObj, func(oldObj *flowcontrolv1beta1.PriorityLevelConfiguration) *flowcontrolv1beta1.PriorityLevelConfigurationSpec { + return &oldObj.Spec + }), oldObj != nil)...) + + // field flowcontrolv1beta1.PriorityLevelConfiguration.Status has no validation + return errs +} + +// Validate_PriorityLevelConfigurationSpec validates an instance of PriorityLevelConfigurationSpec according +// to declarative validation rules in the API schema. +func Validate_PriorityLevelConfigurationSpec(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta1.PriorityLevelConfigurationSpec) (errs field.ErrorList) { + errs = append(errs, validate.Discriminated(ctx, op, fldPath, obj, oldObj, "exempt", func(obj *flowcontrolv1beta1.PriorityLevelConfigurationSpec) *flowcontrolv1beta1.ExemptPriorityLevelConfiguration { + return obj.Exempt + }, func(obj *flowcontrolv1beta1.PriorityLevelConfigurationSpec) flowcontrolv1beta1.PriorityLevelEnablement { + return obj.Type + }, validate.SemanticDeepEqual, func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta1.ExemptPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + errs = append(errs, validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha()...) + return errs + }, []validate.DiscriminatedRule[*flowcontrolv1beta1.ExemptPriorityLevelConfiguration, flowcontrolv1beta1.PriorityLevelEnablement]{ + { + Value: "Exempt", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta1.ExemptPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + { + Value: "Limited", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta1.ExemptPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + })...) + errs = append(errs, validate.Discriminated(ctx, op, fldPath, obj, oldObj, "limited", func(obj *flowcontrolv1beta1.PriorityLevelConfigurationSpec) *flowcontrolv1beta1.LimitedPriorityLevelConfiguration { + return obj.Limited + }, func(obj *flowcontrolv1beta1.PriorityLevelConfigurationSpec) flowcontrolv1beta1.PriorityLevelEnablement { + return obj.Type + }, validate.SemanticDeepEqual, func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta1.LimitedPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + errs = append(errs, validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha()...) + return errs + }, []validate.DiscriminatedRule[*flowcontrolv1beta1.LimitedPriorityLevelConfiguration, flowcontrolv1beta1.PriorityLevelEnablement]{ + { + Value: "Exempt", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta1.LimitedPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + { + Value: "Limited", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta1.LimitedPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.RequiredPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + })...) + + // field flowcontrolv1beta1.PriorityLevelConfigurationSpec.Type + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1beta1.PriorityLevelEnablement, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) { + return nil + } + // call field-attached validations + earlyReturn := false + if e := validate.RequiredValue(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + }(fldPath.Child("type"), &obj.Type, safe.Field(oldObj, func(oldObj *flowcontrolv1beta1.PriorityLevelConfigurationSpec) *flowcontrolv1beta1.PriorityLevelEnablement { + return &oldObj.Type + }), oldObj != nil)...) + + // field flowcontrolv1beta1.PriorityLevelConfigurationSpec.Limited + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1beta1.LimitedPriorityLevelConfiguration, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + }(fldPath.Child("limited"), obj.Limited, safe.Field(oldObj, func(oldObj *flowcontrolv1beta1.PriorityLevelConfigurationSpec) *flowcontrolv1beta1.LimitedPriorityLevelConfiguration { + return oldObj.Limited + }), oldObj != nil)...) + + // field flowcontrolv1beta1.PriorityLevelConfigurationSpec.Exempt + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1beta1.ExemptPriorityLevelConfiguration, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + }(fldPath.Child("exempt"), obj.Exempt, safe.Field(oldObj, func(oldObj *flowcontrolv1beta1.PriorityLevelConfigurationSpec) *flowcontrolv1beta1.ExemptPriorityLevelConfiguration { + return oldObj.Exempt + }), oldObj != nil)...) + + return errs +} diff --git a/pkg/apis/flowcontrol/v1beta2/zz_generated.validations.go b/pkg/apis/flowcontrol/v1beta2/zz_generated.validations.go index 2b709ed6643..08caa53178f 100644 --- a/pkg/apis/flowcontrol/v1beta2/zz_generated.validations.go +++ b/pkg/apis/flowcontrol/v1beta2/zz_generated.validations.go @@ -22,7 +22,16 @@ limitations under the License. package v1beta2 import ( + context "context" + fmt "fmt" + + flowcontrolv1beta2 "k8s.io/api/flowcontrol/v1beta2" + equality "k8s.io/apimachinery/pkg/api/equality" + operation "k8s.io/apimachinery/pkg/api/operation" + safe "k8s.io/apimachinery/pkg/api/safe" + validate "k8s.io/apimachinery/pkg/api/validate" runtime "k8s.io/apimachinery/pkg/runtime" + field "k8s.io/apimachinery/pkg/util/validation/field" ) func init() { localSchemeBuilder.Register(RegisterValidations) } @@ -30,5 +39,182 @@ func init() { localSchemeBuilder.Register(RegisterValidations) } // RegisterValidations adds validation functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterValidations(scheme *runtime.Scheme) error { + // type PriorityLevelConfiguration + scheme.AddValidationFunc((*flowcontrolv1beta2.PriorityLevelConfiguration)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList { + switch op.Request.SubresourcePath() { + case "/": + return Validate_PriorityLevelConfiguration(ctx, op, nil /* fldPath */, obj.(*flowcontrolv1beta2.PriorityLevelConfiguration), safe.Cast[*flowcontrolv1beta2.PriorityLevelConfiguration](oldObj)) + } + return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))} + }) return nil } + +// Validate_PriorityLevelConfiguration validates an instance of PriorityLevelConfiguration according +// to declarative validation rules in the API schema. +func Validate_PriorityLevelConfiguration(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta2.PriorityLevelConfiguration) (errs field.ErrorList) { + // field flowcontrolv1beta2.PriorityLevelConfiguration.TypeMeta has no validation + // field flowcontrolv1beta2.PriorityLevelConfiguration.ObjectMeta has no validation + + // field flowcontrolv1beta2.PriorityLevelConfiguration.Spec + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1beta2.PriorityLevelConfigurationSpec, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + // call the type's validation function + errs = append(errs, Validate_PriorityLevelConfigurationSpec(ctx, op, fldPath, obj, oldObj)...) + return + }(fldPath.Child("spec"), &obj.Spec, safe.Field(oldObj, func(oldObj *flowcontrolv1beta2.PriorityLevelConfiguration) *flowcontrolv1beta2.PriorityLevelConfigurationSpec { + return &oldObj.Spec + }), oldObj != nil)...) + + // field flowcontrolv1beta2.PriorityLevelConfiguration.Status has no validation + return errs +} + +// Validate_PriorityLevelConfigurationSpec validates an instance of PriorityLevelConfigurationSpec according +// to declarative validation rules in the API schema. +func Validate_PriorityLevelConfigurationSpec(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta2.PriorityLevelConfigurationSpec) (errs field.ErrorList) { + errs = append(errs, validate.Discriminated(ctx, op, fldPath, obj, oldObj, "exempt", func(obj *flowcontrolv1beta2.PriorityLevelConfigurationSpec) *flowcontrolv1beta2.ExemptPriorityLevelConfiguration { + return obj.Exempt + }, func(obj *flowcontrolv1beta2.PriorityLevelConfigurationSpec) flowcontrolv1beta2.PriorityLevelEnablement { + return obj.Type + }, validate.SemanticDeepEqual, func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta2.ExemptPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + errs = append(errs, validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha()...) + return errs + }, []validate.DiscriminatedRule[*flowcontrolv1beta2.ExemptPriorityLevelConfiguration, flowcontrolv1beta2.PriorityLevelEnablement]{ + { + Value: "Exempt", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta2.ExemptPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + { + Value: "Limited", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta2.ExemptPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + })...) + errs = append(errs, validate.Discriminated(ctx, op, fldPath, obj, oldObj, "limited", func(obj *flowcontrolv1beta2.PriorityLevelConfigurationSpec) *flowcontrolv1beta2.LimitedPriorityLevelConfiguration { + return obj.Limited + }, func(obj *flowcontrolv1beta2.PriorityLevelConfigurationSpec) flowcontrolv1beta2.PriorityLevelEnablement { + return obj.Type + }, validate.SemanticDeepEqual, func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta2.LimitedPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + errs = append(errs, validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha()...) + return errs + }, []validate.DiscriminatedRule[*flowcontrolv1beta2.LimitedPriorityLevelConfiguration, flowcontrolv1beta2.PriorityLevelEnablement]{ + { + Value: "Exempt", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta2.LimitedPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + { + Value: "Limited", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta2.LimitedPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.RequiredPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + })...) + + // field flowcontrolv1beta2.PriorityLevelConfigurationSpec.Type + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1beta2.PriorityLevelEnablement, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) { + return nil + } + // call field-attached validations + earlyReturn := false + if e := validate.RequiredValue(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + }(fldPath.Child("type"), &obj.Type, safe.Field(oldObj, func(oldObj *flowcontrolv1beta2.PriorityLevelConfigurationSpec) *flowcontrolv1beta2.PriorityLevelEnablement { + return &oldObj.Type + }), oldObj != nil)...) + + // field flowcontrolv1beta2.PriorityLevelConfigurationSpec.Limited + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1beta2.LimitedPriorityLevelConfiguration, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + }(fldPath.Child("limited"), obj.Limited, safe.Field(oldObj, func(oldObj *flowcontrolv1beta2.PriorityLevelConfigurationSpec) *flowcontrolv1beta2.LimitedPriorityLevelConfiguration { + return oldObj.Limited + }), oldObj != nil)...) + + // field flowcontrolv1beta2.PriorityLevelConfigurationSpec.Exempt + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1beta2.ExemptPriorityLevelConfiguration, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + }(fldPath.Child("exempt"), obj.Exempt, safe.Field(oldObj, func(oldObj *flowcontrolv1beta2.PriorityLevelConfigurationSpec) *flowcontrolv1beta2.ExemptPriorityLevelConfiguration { + return oldObj.Exempt + }), oldObj != nil)...) + + return errs +} diff --git a/pkg/apis/flowcontrol/v1beta3/zz_generated.validations.go b/pkg/apis/flowcontrol/v1beta3/zz_generated.validations.go index ab2e8319c4b..ada6f5cdbfc 100644 --- a/pkg/apis/flowcontrol/v1beta3/zz_generated.validations.go +++ b/pkg/apis/flowcontrol/v1beta3/zz_generated.validations.go @@ -22,7 +22,16 @@ limitations under the License. package v1beta3 import ( + context "context" + fmt "fmt" + + flowcontrolv1beta3 "k8s.io/api/flowcontrol/v1beta3" + equality "k8s.io/apimachinery/pkg/api/equality" + operation "k8s.io/apimachinery/pkg/api/operation" + safe "k8s.io/apimachinery/pkg/api/safe" + validate "k8s.io/apimachinery/pkg/api/validate" runtime "k8s.io/apimachinery/pkg/runtime" + field "k8s.io/apimachinery/pkg/util/validation/field" ) func init() { localSchemeBuilder.Register(RegisterValidations) } @@ -30,5 +39,182 @@ func init() { localSchemeBuilder.Register(RegisterValidations) } // RegisterValidations adds validation functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterValidations(scheme *runtime.Scheme) error { + // type PriorityLevelConfiguration + scheme.AddValidationFunc((*flowcontrolv1beta3.PriorityLevelConfiguration)(nil), func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList { + switch op.Request.SubresourcePath() { + case "/": + return Validate_PriorityLevelConfiguration(ctx, op, nil /* fldPath */, obj.(*flowcontrolv1beta3.PriorityLevelConfiguration), safe.Cast[*flowcontrolv1beta3.PriorityLevelConfiguration](oldObj)) + } + return field.ErrorList{field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath()))} + }) return nil } + +// Validate_PriorityLevelConfiguration validates an instance of PriorityLevelConfiguration according +// to declarative validation rules in the API schema. +func Validate_PriorityLevelConfiguration(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta3.PriorityLevelConfiguration) (errs field.ErrorList) { + // field flowcontrolv1beta3.PriorityLevelConfiguration.TypeMeta has no validation + // field flowcontrolv1beta3.PriorityLevelConfiguration.ObjectMeta has no validation + + // field flowcontrolv1beta3.PriorityLevelConfiguration.Spec + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1beta3.PriorityLevelConfigurationSpec, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + // call the type's validation function + errs = append(errs, Validate_PriorityLevelConfigurationSpec(ctx, op, fldPath, obj, oldObj)...) + return + }(fldPath.Child("spec"), &obj.Spec, safe.Field(oldObj, func(oldObj *flowcontrolv1beta3.PriorityLevelConfiguration) *flowcontrolv1beta3.PriorityLevelConfigurationSpec { + return &oldObj.Spec + }), oldObj != nil)...) + + // field flowcontrolv1beta3.PriorityLevelConfiguration.Status has no validation + return errs +} + +// Validate_PriorityLevelConfigurationSpec validates an instance of PriorityLevelConfigurationSpec according +// to declarative validation rules in the API schema. +func Validate_PriorityLevelConfigurationSpec(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta3.PriorityLevelConfigurationSpec) (errs field.ErrorList) { + errs = append(errs, validate.Discriminated(ctx, op, fldPath, obj, oldObj, "exempt", func(obj *flowcontrolv1beta3.PriorityLevelConfigurationSpec) *flowcontrolv1beta3.ExemptPriorityLevelConfiguration { + return obj.Exempt + }, func(obj *flowcontrolv1beta3.PriorityLevelConfigurationSpec) flowcontrolv1beta3.PriorityLevelEnablement { + return obj.Type + }, validate.SemanticDeepEqual, func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta3.ExemptPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + errs = append(errs, validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha()...) + return errs + }, []validate.DiscriminatedRule[*flowcontrolv1beta3.ExemptPriorityLevelConfiguration, flowcontrolv1beta3.PriorityLevelEnablement]{ + { + Value: "Exempt", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta3.ExemptPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + { + Value: "Limited", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta3.ExemptPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + })...) + errs = append(errs, validate.Discriminated(ctx, op, fldPath, obj, oldObj, "limited", func(obj *flowcontrolv1beta3.PriorityLevelConfigurationSpec) *flowcontrolv1beta3.LimitedPriorityLevelConfiguration { + return obj.Limited + }, func(obj *flowcontrolv1beta3.PriorityLevelConfigurationSpec) flowcontrolv1beta3.PriorityLevelEnablement { + return obj.Type + }, validate.SemanticDeepEqual, func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta3.LimitedPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + errs = append(errs, validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha()...) + return errs + }, []validate.DiscriminatedRule[*flowcontrolv1beta3.LimitedPriorityLevelConfiguration, flowcontrolv1beta3.PriorityLevelEnablement]{ + { + Value: "Exempt", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta3.LimitedPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.ForbiddenPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + { + Value: "Limited", Validation: func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *flowcontrolv1beta3.LimitedPriorityLevelConfiguration) field.ErrorList { + errs := field.ErrorList{} + earlyReturn := false + if e := validate.RequiredPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return errs + } + return errs + }}, + })...) + + // field flowcontrolv1beta3.PriorityLevelConfigurationSpec.Type + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1beta3.PriorityLevelEnablement, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && (obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj)) { + return nil + } + // call field-attached validations + earlyReturn := false + if e := validate.RequiredValue(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + }(fldPath.Child("type"), &obj.Type, safe.Field(oldObj, func(oldObj *flowcontrolv1beta3.PriorityLevelConfigurationSpec) *flowcontrolv1beta3.PriorityLevelEnablement { + return &oldObj.Type + }), oldObj != nil)...) + + // field flowcontrolv1beta3.PriorityLevelConfigurationSpec.Limited + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1beta3.LimitedPriorityLevelConfiguration, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + }(fldPath.Child("limited"), obj.Limited, safe.Field(oldObj, func(oldObj *flowcontrolv1beta3.PriorityLevelConfigurationSpec) *flowcontrolv1beta3.LimitedPriorityLevelConfiguration { + return oldObj.Limited + }), oldObj != nil)...) + + // field flowcontrolv1beta3.PriorityLevelConfigurationSpec.Exempt + errs = append(errs, + func(fldPath *field.Path, obj, oldObj *flowcontrolv1beta3.ExemptPriorityLevelConfiguration, oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkAlpha(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + }(fldPath.Child("exempt"), obj.Exempt, safe.Field(oldObj, func(oldObj *flowcontrolv1beta3.PriorityLevelConfigurationSpec) *flowcontrolv1beta3.ExemptPriorityLevelConfiguration { + return oldObj.Exempt + }), oldObj != nil)...) + + return errs +} diff --git a/pkg/apis/flowcontrol/validation/validation.go b/pkg/apis/flowcontrol/validation/validation.go index c82f3177abe..2cc01120601 100644 --- a/pkg/apis/flowcontrol/validation/validation.go +++ b/pkg/apis/flowcontrol/validation/validation.go @@ -400,18 +400,18 @@ func ValidatePriorityLevelConfigurationSpec(spec *flowcontrol.PriorityLevelConfi switch spec.Type { case flowcontrol.PriorityLevelEnablementExempt: if spec.Limited != nil { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("limited"), "must be nil if the type is not Limited")) + allErrs = append(allErrs, field.Forbidden(fldPath.Child("limited"), "must be nil if the type is not Limited").MarkCoveredByDeclarative()) } if spec.Exempt != nil { allErrs = append(allErrs, ValidateExemptPriorityLevelConfiguration(spec.Exempt, fldPath.Child("exempt"))...) } case flowcontrol.PriorityLevelEnablementLimited: if spec.Exempt != nil { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("exempt"), "must be nil if the type is Limited")) + allErrs = append(allErrs, field.Forbidden(fldPath.Child("exempt"), "must be nil if the type is Limited").MarkCoveredByDeclarative()) } if spec.Limited == nil { - allErrs = append(allErrs, field.Required(fldPath.Child("limited"), "must not be empty when type is Limited")) + allErrs = append(allErrs, field.Required(fldPath.Child("limited"), "must not be empty when type is Limited").MarkCoveredByDeclarative()) } else { allErrs = append(allErrs, ValidateLimitedPriorityLevelConfiguration(spec.Limited, requestGV, fldPath.Child("limited"), opts)...) } diff --git a/pkg/apis/flowcontrol/validation/validation_test.go b/pkg/apis/flowcontrol/validation/validation_test.go index 1cb93eaed9d..f0f003af186 100644 --- a/pkg/apis/flowcontrol/validation/validation_test.go +++ b/pkg/apis/flowcontrol/validation/validation_test.go @@ -856,7 +856,7 @@ func TestPriorityLevelConfigurationValidation(t *testing.T) { priorityLevelConfiguration: exemptTypeRepurposed, expectedErrors: field.ErrorList{ field.Invalid(field.NewPath("spec").Child("type"), flowcontrol.PriorityLevelEnablementLimited, "must be 'Exempt' if and only if `name` is 'exempt'"), - field.Forbidden(field.NewPath("spec").Child("exempt"), "must be nil if the type is Limited"), + field.Forbidden(field.NewPath("spec").Child("exempt"), "must be nil if the type is Limited").MarkCoveredByDeclarative(), field.Invalid(field.NewPath("spec"), exemptTypeRepurposed.Spec, "spec of 'exempt' except the 'spec.exempt' field must equal the fixed value"), }, }, { @@ -869,7 +869,7 @@ func TestPriorityLevelConfigurationValidation(t *testing.T) { }, expectedErrors: field.ErrorList{ field.Invalid(field.NewPath("spec"), badExemptSpec3, "spec of 'exempt' except the 'spec.exempt' field must equal the fixed value"), - field.Forbidden(field.NewPath("spec").Child("limited"), "must be nil if the type is not Limited"), + field.Forbidden(field.NewPath("spec").Child("limited"), "must be nil if the type is not Limited").MarkCoveredByDeclarative(), }, }, { name: "admins are allowed to change the Exempt field of the 'exempt' pl", @@ -892,8 +892,8 @@ func TestPriorityLevelConfigurationValidation(t *testing.T) { }, }, expectedErrors: field.ErrorList{ - field.Forbidden(field.NewPath("spec").Child("exempt"), "must be nil if the type is Limited"), - field.Required(field.NewPath("spec").Child("limited"), "must not be empty when type is Limited"), + field.Forbidden(field.NewPath("spec").Child("exempt"), "must be nil if the type is Limited").MarkCoveredByDeclarative(), + field.Required(field.NewPath("spec").Child("limited"), "must not be empty when type is Limited").MarkCoveredByDeclarative(), }, }, { name: "limited requires more details", @@ -905,7 +905,7 @@ func TestPriorityLevelConfigurationValidation(t *testing.T) { Type: flowcontrol.PriorityLevelEnablementLimited, }, }, - expectedErrors: field.ErrorList{field.Required(field.NewPath("spec").Child("limited"), "must not be empty when type is Limited")}, + expectedErrors: field.ErrorList{field.Required(field.NewPath("spec").Child("limited"), "must not be empty when type is Limited").MarkCoveredByDeclarative()}, }, { name: "max-in-flight should work", priorityLevelConfiguration: &flowcontrol.PriorityLevelConfiguration{ diff --git a/pkg/registry/flowcontrol/prioritylevelconfiguration/declarative_validation_test.go b/pkg/registry/flowcontrol/prioritylevelconfiguration/declarative_validation_test.go index 699b5f75080..623605fd2bc 100644 --- a/pkg/registry/flowcontrol/prioritylevelconfiguration/declarative_validation_test.go +++ b/pkg/registry/flowcontrol/prioritylevelconfiguration/declarative_validation_test.go @@ -42,10 +42,52 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) { APIVersion: apiVersion, }) + specPath := field.NewPath("spec") + testCases := map[string]struct { input flowcontrol.PriorityLevelConfiguration expectedErrs field.ErrorList - }{} + }{ + "valid: Limited allows Reject without queuing": { + input: mkPLC(), + }, + "valid: Queue requires queuing": { + input: mkPLC(tweakLimitResponseType(flowcontrol.LimitResponseTypeQueue)), + }, + "valid: Exempt without exempt config": { + input: mkPLC(tweakExempt()), + }, + "valid: Exempt with exempt config": { + input: mkPLC(tweakExempt(), tweakExemptConfig(&flowcontrol.ExemptPriorityLevelConfiguration{ + NominalConcurrencyShares: ptrInt32(100), + })), + }, + "spec.type: Limited with limited=nil": { + input: mkPLC(tweakLimited(nil)), + expectedErrs: field.ErrorList{ + field.Required(specPath.Child("limited"), "").MarkCoveredByDeclarative().MarkAlpha(), + }, + }, + "spec.type: Exempt with limited set": { + input: mkPLC(tweakExempt(), tweakLimited(&flowcontrol.LimitedPriorityLevelConfiguration{ + NominalConcurrencyShares: 100, + LimitResponse: flowcontrol.LimitResponse{ + Type: flowcontrol.LimitResponseTypeReject, + }, + })), + expectedErrs: field.ErrorList{ + // Mandatory object check: spec of 'exempt' differs from bootstrap (HW-only) + field.Invalid(specPath, nil, "").MarkFromImperative(), + field.Forbidden(specPath.Child("limited"), "").MarkCoveredByDeclarative().MarkAlpha(), + }, + }, + "spec.type: Limited with exempt set": { + input: mkPLC(tweakExemptConfig(&flowcontrol.ExemptPriorityLevelConfiguration{})), + expectedErrs: field.ErrorList{ + field.Forbidden(specPath.Child("exempt"), "").MarkCoveredByDeclarative().MarkAlpha(), + }, + }, + } for name, tc := range testCases { t.Run(name, func(t *testing.T) { @@ -63,11 +105,36 @@ func TestDeclarativeValidateUpdate(t *testing.T) { } func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) { + specPath := field.NewPath("spec") + testCases := map[string]struct { old flowcontrol.PriorityLevelConfiguration update flowcontrol.PriorityLevelConfiguration expectedErrs field.ErrorList - }{} + }{ + "valid update (no changes)": { + old: mkPLC(), + update: mkPLC(), + }, + "valid update: Reject to Queue": { + old: mkPLC(), + update: mkPLC(tweakLimitResponseType(flowcontrol.LimitResponseTypeQueue)), + }, + "update: limited set to nil": { + old: mkPLC(), + update: mkPLC(tweakLimited(nil)), + expectedErrs: field.ErrorList{ + field.Required(specPath.Child("limited"), "").MarkCoveredByDeclarative().MarkAlpha(), + }, + }, + "update: add exempt field to Limited PLC": { + old: mkPLC(), + update: mkPLC(tweakExemptConfig(&flowcontrol.ExemptPriorityLevelConfiguration{})), + expectedErrs: field.ErrorList{ + field.Forbidden(specPath.Child("exempt"), "").MarkCoveredByDeclarative().MarkAlpha(), + }, + }, + } for name, tc := range testCases { t.Run(name, func(t *testing.T) { diff --git a/staging/src/k8s.io/api/flowcontrol/v1/generated.proto b/staging/src/k8s.io/api/flowcontrol/v1/generated.proto index 33a135889e5..547eb655d6a 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1/generated.proto +++ b/staging/src/k8s.io/api/flowcontrol/v1/generated.proto @@ -367,11 +367,16 @@ message PriorityLevelConfigurationSpec { // capacity is made available exclusively to this priority level. // Required. // +unionDiscriminator + // +k8s:alpha(since: "1.36")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:discriminator optional string type = 1; // `limited` specifies how requests are handled for a Limited priority level. // This field must be non-empty if and only if `type` is `"Limited"`. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:forbidden optional LimitedPriorityLevelConfiguration limited = 2; // `exempt` specifies how requests are handled for an exempt priority level. @@ -380,6 +385,9 @@ message PriorityLevelConfigurationSpec { // If empty and `type` is `"Exempt"` then the default values // for `ExemptPriorityLevelConfiguration` apply. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:forbidden optional ExemptPriorityLevelConfiguration exempt = 3; } diff --git a/staging/src/k8s.io/api/flowcontrol/v1/types.go b/staging/src/k8s.io/api/flowcontrol/v1/types.go index ad72bcee228..f6eae5bc429 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1/types.go +++ b/staging/src/k8s.io/api/flowcontrol/v1/types.go @@ -429,11 +429,16 @@ type PriorityLevelConfigurationSpec struct { // capacity is made available exclusively to this priority level. // Required. // +unionDiscriminator + // +k8s:alpha(since: "1.36")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:discriminator Type PriorityLevelEnablement `json:"type" protobuf:"bytes,1,opt,name=type"` // `limited` specifies how requests are handled for a Limited priority level. // This field must be non-empty if and only if `type` is `"Limited"`. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:forbidden Limited *LimitedPriorityLevelConfiguration `json:"limited,omitempty" protobuf:"bytes,2,opt,name=limited"` // `exempt` specifies how requests are handled for an exempt priority level. @@ -442,6 +447,9 @@ type PriorityLevelConfigurationSpec struct { // If empty and `type` is `"Exempt"` then the default values // for `ExemptPriorityLevelConfiguration` apply. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:forbidden Exempt *ExemptPriorityLevelConfiguration `json:"exempt,omitempty" protobuf:"bytes,3,opt,name=exempt"` } diff --git a/staging/src/k8s.io/api/flowcontrol/v1beta1/generated.proto b/staging/src/k8s.io/api/flowcontrol/v1beta1/generated.proto index 61ed3833aee..c66f3c9953a 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1beta1/generated.proto +++ b/staging/src/k8s.io/api/flowcontrol/v1beta1/generated.proto @@ -360,11 +360,16 @@ message PriorityLevelConfigurationSpec { // capacity is made available exclusively to this priority level. // Required. // +unionDiscriminator + // +k8s:alpha(since: "1.36")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:discriminator optional string type = 1; // `limited` specifies how requests are handled for a Limited priority level. // This field must be non-empty if and only if `type` is `"Limited"`. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:forbidden optional LimitedPriorityLevelConfiguration limited = 2; // `exempt` specifies how requests are handled for an exempt priority level. @@ -373,6 +378,9 @@ message PriorityLevelConfigurationSpec { // If empty and `type` is `"Exempt"` then the default values // for `ExemptPriorityLevelConfiguration` apply. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:forbidden optional ExemptPriorityLevelConfiguration exempt = 3; } diff --git a/staging/src/k8s.io/api/flowcontrol/v1beta1/types.go b/staging/src/k8s.io/api/flowcontrol/v1beta1/types.go index abc3e420096..6347fd6cbec 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1beta1/types.go +++ b/staging/src/k8s.io/api/flowcontrol/v1beta1/types.go @@ -431,11 +431,16 @@ type PriorityLevelConfigurationSpec struct { // capacity is made available exclusively to this priority level. // Required. // +unionDiscriminator + // +k8s:alpha(since: "1.36")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:discriminator Type PriorityLevelEnablement `json:"type" protobuf:"bytes,1,opt,name=type"` // `limited` specifies how requests are handled for a Limited priority level. // This field must be non-empty if and only if `type` is `"Limited"`. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:forbidden Limited *LimitedPriorityLevelConfiguration `json:"limited,omitempty" protobuf:"bytes,2,opt,name=limited"` // `exempt` specifies how requests are handled for an exempt priority level. @@ -444,6 +449,9 @@ type PriorityLevelConfigurationSpec struct { // If empty and `type` is `"Exempt"` then the default values // for `ExemptPriorityLevelConfiguration` apply. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:forbidden Exempt *ExemptPriorityLevelConfiguration `json:"exempt,omitempty" protobuf:"bytes,3,opt,name=exempt"` } diff --git a/staging/src/k8s.io/api/flowcontrol/v1beta2/generated.proto b/staging/src/k8s.io/api/flowcontrol/v1beta2/generated.proto index d6073fc9259..afc75244e72 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1beta2/generated.proto +++ b/staging/src/k8s.io/api/flowcontrol/v1beta2/generated.proto @@ -360,11 +360,16 @@ message PriorityLevelConfigurationSpec { // capacity is made available exclusively to this priority level. // Required. // +unionDiscriminator + // +k8s:alpha(since: "1.36")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:discriminator optional string type = 1; // `limited` specifies how requests are handled for a Limited priority level. // This field must be non-empty if and only if `type` is `"Limited"`. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:forbidden optional LimitedPriorityLevelConfiguration limited = 2; // `exempt` specifies how requests are handled for an exempt priority level. @@ -373,6 +378,9 @@ message PriorityLevelConfigurationSpec { // If empty and `type` is `"Exempt"` then the default values // for `ExemptPriorityLevelConfiguration` apply. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:forbidden optional ExemptPriorityLevelConfiguration exempt = 3; } diff --git a/staging/src/k8s.io/api/flowcontrol/v1beta2/types.go b/staging/src/k8s.io/api/flowcontrol/v1beta2/types.go index c66cb173f4a..712e7b95b70 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1beta2/types.go +++ b/staging/src/k8s.io/api/flowcontrol/v1beta2/types.go @@ -431,11 +431,16 @@ type PriorityLevelConfigurationSpec struct { // capacity is made available exclusively to this priority level. // Required. // +unionDiscriminator + // +k8s:alpha(since: "1.36")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:discriminator Type PriorityLevelEnablement `json:"type" protobuf:"bytes,1,opt,name=type"` // `limited` specifies how requests are handled for a Limited priority level. // This field must be non-empty if and only if `type` is `"Limited"`. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:forbidden Limited *LimitedPriorityLevelConfiguration `json:"limited,omitempty" protobuf:"bytes,2,opt,name=limited"` // `exempt` specifies how requests are handled for an exempt priority level. @@ -444,6 +449,9 @@ type PriorityLevelConfigurationSpec struct { // If empty and `type` is `"Exempt"` then the default values // for `ExemptPriorityLevelConfiguration` apply. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:forbidden Exempt *ExemptPriorityLevelConfiguration `json:"exempt,omitempty" protobuf:"bytes,3,opt,name=exempt"` } diff --git a/staging/src/k8s.io/api/flowcontrol/v1beta3/generated.proto b/staging/src/k8s.io/api/flowcontrol/v1beta3/generated.proto index c6504d4353f..1d6200c1e02 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1beta3/generated.proto +++ b/staging/src/k8s.io/api/flowcontrol/v1beta3/generated.proto @@ -362,11 +362,16 @@ message PriorityLevelConfigurationSpec { // capacity is made available exclusively to this priority level. // Required. // +unionDiscriminator + // +k8s:alpha(since: "1.36")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:discriminator optional string type = 1; // `limited` specifies how requests are handled for a Limited priority level. // This field must be non-empty if and only if `type` is `"Limited"`. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:forbidden optional LimitedPriorityLevelConfiguration limited = 2; // `exempt` specifies how requests are handled for an exempt priority level. @@ -375,6 +380,9 @@ message PriorityLevelConfigurationSpec { // If empty and `type` is `"Exempt"` then the default values // for `ExemptPriorityLevelConfiguration` apply. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:forbidden optional ExemptPriorityLevelConfiguration exempt = 3; } diff --git a/staging/src/k8s.io/api/flowcontrol/v1beta3/types.go b/staging/src/k8s.io/api/flowcontrol/v1beta3/types.go index 0ffc22a2365..013c02f12c9 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1beta3/types.go +++ b/staging/src/k8s.io/api/flowcontrol/v1beta3/types.go @@ -447,11 +447,16 @@ type PriorityLevelConfigurationSpec struct { // capacity is made available exclusively to this priority level. // Required. // +unionDiscriminator + // +k8s:alpha(since: "1.36")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:discriminator Type PriorityLevelEnablement `json:"type" protobuf:"bytes,1,opt,name=type"` // `limited` specifies how requests are handled for a Limited priority level. // This field must be non-empty if and only if `type` is `"Limited"`. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:required + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:forbidden Limited *LimitedPriorityLevelConfiguration `json:"limited,omitempty" protobuf:"bytes,2,opt,name=limited"` // `exempt` specifies how requests are handled for an exempt priority level. @@ -460,6 +465,9 @@ type PriorityLevelConfigurationSpec struct { // If empty and `type` is `"Exempt"` then the default values // for `ExemptPriorityLevelConfiguration` apply. // +optional + // +k8s:alpha(since: "1.36")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Exempt")=+k8s:optional + // +k8s:alpha(since: "1.36")=+k8s:member("Limited")=+k8s:forbidden Exempt *ExemptPriorityLevelConfiguration `json:"exempt,omitempty" protobuf:"bytes,3,opt,name=exempt"` }