diff --git a/pkg/api/testing/validation_test.go b/pkg/api/testing/validation_test.go index 23ffa1d99f2..35e2b95333b 100644 --- a/pkg/api/testing/validation_test.go +++ b/pkg/api/testing/validation_test.go @@ -64,6 +64,10 @@ func TestVersionedValidationByFuzzing(t *testing.T) { {Group: "admissionregistration.k8s.io", Version: "v1"}, {Group: "admissionregistration.k8s.io", Version: "v1beta1"}, {Group: "admissionregistration.k8s.io", Version: "v1alpha1"}, + {Group: "flowcontrol.apiserver.k8s.io", Version: "v1"}, + {Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta3"}, + {Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta2"}, + {Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta1"}, } // subresourceOnly specifies the subresource path for types that can only be validated diff --git a/pkg/apis/flowcontrol/v1/zz_generated.validations.go b/pkg/apis/flowcontrol/v1/zz_generated.validations.go index 5242051cc3b..52b456af962 100644 --- a/pkg/apis/flowcontrol/v1/zz_generated.validations.go +++ b/pkg/apis/flowcontrol/v1/zz_generated.validations.go @@ -39,6 +39,21 @@ 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 FlowSchema + scheme.AddValidationFunc( + (*flowcontrolv1.FlowSchema)(nil), + func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList { + switch op.Request.SubresourcePath() { + case "/", "/status": + return Validate_FlowSchema( + ctx, op, nil, /* fldPath */ + obj.(*flowcontrolv1.FlowSchema), + safe.Cast[*flowcontrolv1.FlowSchema](oldObj)) + } + return field.ErrorList{ + field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath())), + } + }) // type PriorityLevelConfiguration scheme.AddValidationFunc( (*flowcontrolv1.PriorityLevelConfiguration)(nil), @@ -57,6 +72,86 @@ func RegisterValidations(scheme *runtime.Scheme) error { return nil } +// Validate_FlowSchema validates an instance of FlowSchema according +// to declarative validation rules in the API schema. +func Validate_FlowSchema( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1.FlowSchema) (errs field.ErrorList) { + + // field flowcontrolv1.FlowSchema.TypeMeta has no validation + // field flowcontrolv1.FlowSchema.ObjectMeta has no validation + + { // field flowcontrolv1.FlowSchema.Spec + fn := func( + fldPath *field.Path, + obj, oldObj *flowcontrolv1.FlowSchemaSpec, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call the type's validation function + errs = append(errs, Validate_FlowSchemaSpec(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1.FlowSchema) *flowcontrolv1.FlowSchemaSpec { + return &oldObj.Spec + }) + errs = append(errs, fn(fldPath.Child("spec"), &obj.Spec, oldVal, oldObj != nil)...) + } + + // field flowcontrolv1.FlowSchema.Status has no validation + return errs +} + +// Validate_FlowSchemaSpec validates an instance of FlowSchemaSpec according +// to declarative validation rules in the API schema. +func Validate_FlowSchemaSpec( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1.FlowSchemaSpec) (errs field.ErrorList) { + + // field flowcontrolv1.FlowSchemaSpec.PriorityLevelConfiguration has no validation + // field flowcontrolv1.FlowSchemaSpec.MatchingPrecedence has no validation + // field flowcontrolv1.FlowSchemaSpec.DistinguisherMethod has no validation + + { // field flowcontrolv1.FlowSchemaSpec.Rules + fn := func( + fldPath *field.Path, + obj, oldObj []flowcontrolv1.PolicyRulesWithSubjects, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalSlice(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // iterate the list and call the type's validation function + if e := validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_PolicyRulesWithSubjects); len(e) != 0 { + errs = append(errs, e...) + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1.FlowSchemaSpec) []flowcontrolv1.PolicyRulesWithSubjects { + return oldObj.Rules + }) + errs = append(errs, fn(fldPath.Child("rules"), obj.Rules, oldVal, oldObj != nil)...) + } + + return errs +} + // Validate_LimitResponse validates an instance of LimitResponse according // to declarative validation rules in the API schema. func Validate_LimitResponse( @@ -187,6 +282,50 @@ func Validate_LimitedPriorityLevelConfiguration( return errs } +// Validate_PolicyRulesWithSubjects validates an instance of PolicyRulesWithSubjects according +// to declarative validation rules in the API schema. +func Validate_PolicyRulesWithSubjects( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1.PolicyRulesWithSubjects) (errs field.ErrorList) { + + { // field flowcontrolv1.PolicyRulesWithSubjects.Subjects + fn := func( + fldPath *field.Path, + obj, oldObj []flowcontrolv1.Subject, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.RequiredSlice(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // iterate the list and call the type's validation function + if e := validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_Subject); len(e) != 0 { + errs = append(errs, e...) + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1.PolicyRulesWithSubjects) []flowcontrolv1.Subject { + return oldObj.Subjects + }) + errs = append(errs, fn(fldPath.Child("subjects"), obj.Subjects, oldVal, oldObj != nil)...) + } + + // field flowcontrolv1.PolicyRulesWithSubjects.ResourceRules has no validation + // field flowcontrolv1.PolicyRulesWithSubjects.NonResourceRules has no validation + return errs +} + // Validate_PriorityLevelConfiguration validates an instance of PriorityLevelConfiguration according // to declarative validation rules in the API schema. func Validate_PriorityLevelConfiguration( @@ -381,3 +520,123 @@ func Validate_PriorityLevelConfigurationSpec( return errs } + +var unionMembershipFor_k8s_io_api_flowcontrol_v1_Subject_ = validate.NewUnionMembership(validate.NewUnionMember("user")) + +// Validate_Subject validates an instance of Subject according +// to declarative validation rules in the API schema. +func Validate_Subject( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1.Subject) (errs field.ErrorList) { + + if e := validate.Union(ctx, op, fldPath, obj, oldObj, unionMembershipFor_k8s_io_api_flowcontrol_v1_Subject_, + func(obj *flowcontrolv1.Subject) bool { + if obj == nil { + return false + } + return obj.User != nil + }); len(e) != 0 { + errs = append(errs, e...) + } + + { // field flowcontrolv1.Subject.Kind + fn := func( + fldPath *field.Path, + obj, oldObj *flowcontrolv1.SubjectKind, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if 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).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1.Subject) *flowcontrolv1.SubjectKind { + return &oldObj.Kind + }) + errs = append(errs, fn(fldPath.Child("kind"), &obj.Kind, oldVal, oldObj != nil)...) + } + + { // field flowcontrolv1.Subject.User + fn := func( + fldPath *field.Path, + obj, oldObj *flowcontrolv1.UserSubject, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_UserSubject(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1.Subject) *flowcontrolv1.UserSubject { + return oldObj.User + }) + errs = append(errs, fn(fldPath.Child("user"), obj.User, oldVal, oldObj != nil)...) + } + + // field flowcontrolv1.Subject.Group has no validation + // field flowcontrolv1.Subject.ServiceAccount has no validation + return errs +} + +// Validate_UserSubject validates an instance of UserSubject according +// to declarative validation rules in the API schema. +func Validate_UserSubject( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1.UserSubject) (errs field.ErrorList) { + + { // field flowcontrolv1.UserSubject.Name + fn := func( + fldPath *field.Path, + obj, oldObj *string, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if 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).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1.UserSubject) *string { + return &oldObj.Name + }) + errs = append(errs, fn(fldPath.Child("name"), &obj.Name, oldVal, 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 7ae9ec27615..d1299484852 100644 --- a/pkg/apis/flowcontrol/v1beta1/zz_generated.validations.go +++ b/pkg/apis/flowcontrol/v1beta1/zz_generated.validations.go @@ -39,6 +39,21 @@ 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 FlowSchema + scheme.AddValidationFunc( + (*flowcontrolv1beta1.FlowSchema)(nil), + func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList { + switch op.Request.SubresourcePath() { + case "/", "/status": + return Validate_FlowSchema( + ctx, op, nil, /* fldPath */ + obj.(*flowcontrolv1beta1.FlowSchema), + safe.Cast[*flowcontrolv1beta1.FlowSchema](oldObj)) + } + return field.ErrorList{ + field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath())), + } + }) // type PriorityLevelConfiguration scheme.AddValidationFunc( (*flowcontrolv1beta1.PriorityLevelConfiguration)(nil), @@ -57,6 +72,86 @@ func RegisterValidations(scheme *runtime.Scheme) error { return nil } +// Validate_FlowSchema validates an instance of FlowSchema according +// to declarative validation rules in the API schema. +func Validate_FlowSchema( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta1.FlowSchema) (errs field.ErrorList) { + + // field flowcontrolv1beta1.FlowSchema.TypeMeta has no validation + // field flowcontrolv1beta1.FlowSchema.ObjectMeta has no validation + + { // field flowcontrolv1beta1.FlowSchema.Spec + fn := func( + fldPath *field.Path, + obj, oldObj *flowcontrolv1beta1.FlowSchemaSpec, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call the type's validation function + errs = append(errs, Validate_FlowSchemaSpec(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta1.FlowSchema) *flowcontrolv1beta1.FlowSchemaSpec { + return &oldObj.Spec + }) + errs = append(errs, fn(fldPath.Child("spec"), &obj.Spec, oldVal, oldObj != nil)...) + } + + // field flowcontrolv1beta1.FlowSchema.Status has no validation + return errs +} + +// Validate_FlowSchemaSpec validates an instance of FlowSchemaSpec according +// to declarative validation rules in the API schema. +func Validate_FlowSchemaSpec( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta1.FlowSchemaSpec) (errs field.ErrorList) { + + // field flowcontrolv1beta1.FlowSchemaSpec.PriorityLevelConfiguration has no validation + // field flowcontrolv1beta1.FlowSchemaSpec.MatchingPrecedence has no validation + // field flowcontrolv1beta1.FlowSchemaSpec.DistinguisherMethod has no validation + + { // field flowcontrolv1beta1.FlowSchemaSpec.Rules + fn := func( + fldPath *field.Path, + obj, oldObj []flowcontrolv1beta1.PolicyRulesWithSubjects, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalSlice(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // iterate the list and call the type's validation function + if e := validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_PolicyRulesWithSubjects); len(e) != 0 { + errs = append(errs, e...) + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta1.FlowSchemaSpec) []flowcontrolv1beta1.PolicyRulesWithSubjects { + return oldObj.Rules + }) + errs = append(errs, fn(fldPath.Child("rules"), obj.Rules, oldVal, oldObj != nil)...) + } + + return errs +} + // Validate_LimitResponse validates an instance of LimitResponse according // to declarative validation rules in the API schema. func Validate_LimitResponse( @@ -189,6 +284,50 @@ func Validate_LimitedPriorityLevelConfiguration( return errs } +// Validate_PolicyRulesWithSubjects validates an instance of PolicyRulesWithSubjects according +// to declarative validation rules in the API schema. +func Validate_PolicyRulesWithSubjects( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta1.PolicyRulesWithSubjects) (errs field.ErrorList) { + + { // field flowcontrolv1beta1.PolicyRulesWithSubjects.Subjects + fn := func( + fldPath *field.Path, + obj, oldObj []flowcontrolv1beta1.Subject, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.RequiredSlice(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // iterate the list and call the type's validation function + if e := validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_Subject); len(e) != 0 { + errs = append(errs, e...) + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta1.PolicyRulesWithSubjects) []flowcontrolv1beta1.Subject { + return oldObj.Subjects + }) + errs = append(errs, fn(fldPath.Child("subjects"), obj.Subjects, oldVal, oldObj != nil)...) + } + + // field flowcontrolv1beta1.PolicyRulesWithSubjects.ResourceRules has no validation + // field flowcontrolv1beta1.PolicyRulesWithSubjects.NonResourceRules has no validation + return errs +} + // Validate_PriorityLevelConfiguration validates an instance of PriorityLevelConfiguration according // to declarative validation rules in the API schema. func Validate_PriorityLevelConfiguration( @@ -383,3 +522,129 @@ func Validate_PriorityLevelConfigurationSpec( return errs } + +var unionMembershipFor_k8s_io_api_flowcontrol_v1beta1_Subject_ = validate.NewDiscriminatedUnionMembership("kind", validate.NewDiscriminatedUnionMember("user", "User")) + +// Validate_Subject validates an instance of Subject according +// to declarative validation rules in the API schema. +func Validate_Subject( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta1.Subject) (errs field.ErrorList) { + + if e := validate.DiscriminatedUnion(ctx, op, fldPath, obj, oldObj, unionMembershipFor_k8s_io_api_flowcontrol_v1beta1_Subject_, + func(obj *flowcontrolv1beta1.Subject) string { + if obj == nil { + return "" + } + return string(obj.Kind) + }, + func(obj *flowcontrolv1beta1.Subject) bool { + if obj == nil { + return false + } + return obj.User != nil + }); len(e) != 0 { + errs = append(errs, e...) + } + + { // field flowcontrolv1beta1.Subject.Kind + fn := func( + fldPath *field.Path, + obj, oldObj *flowcontrolv1beta1.SubjectKind, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if 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).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta1.Subject) *flowcontrolv1beta1.SubjectKind { + return &oldObj.Kind + }) + errs = append(errs, fn(fldPath.Child("kind"), &obj.Kind, oldVal, oldObj != nil)...) + } + + { // field flowcontrolv1beta1.Subject.User + fn := func( + fldPath *field.Path, + obj, oldObj *flowcontrolv1beta1.UserSubject, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_UserSubject(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta1.Subject) *flowcontrolv1beta1.UserSubject { + return oldObj.User + }) + errs = append(errs, fn(fldPath.Child("user"), obj.User, oldVal, oldObj != nil)...) + } + + // field flowcontrolv1beta1.Subject.Group has no validation + // field flowcontrolv1beta1.Subject.ServiceAccount has no validation + return errs +} + +// Validate_UserSubject validates an instance of UserSubject according +// to declarative validation rules in the API schema. +func Validate_UserSubject( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta1.UserSubject) (errs field.ErrorList) { + + { // field flowcontrolv1beta1.UserSubject.Name + fn := func( + fldPath *field.Path, + obj, oldObj *string, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if 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).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta1.UserSubject) *string { + return &oldObj.Name + }) + errs = append(errs, fn(fldPath.Child("name"), &obj.Name, oldVal, 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 774e82d6006..e1c413a7ce0 100644 --- a/pkg/apis/flowcontrol/v1beta2/zz_generated.validations.go +++ b/pkg/apis/flowcontrol/v1beta2/zz_generated.validations.go @@ -39,6 +39,21 @@ 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 FlowSchema + scheme.AddValidationFunc( + (*flowcontrolv1beta2.FlowSchema)(nil), + func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList { + switch op.Request.SubresourcePath() { + case "/", "/status": + return Validate_FlowSchema( + ctx, op, nil, /* fldPath */ + obj.(*flowcontrolv1beta2.FlowSchema), + safe.Cast[*flowcontrolv1beta2.FlowSchema](oldObj)) + } + return field.ErrorList{ + field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath())), + } + }) // type PriorityLevelConfiguration scheme.AddValidationFunc( (*flowcontrolv1beta2.PriorityLevelConfiguration)(nil), @@ -57,6 +72,86 @@ func RegisterValidations(scheme *runtime.Scheme) error { return nil } +// Validate_FlowSchema validates an instance of FlowSchema according +// to declarative validation rules in the API schema. +func Validate_FlowSchema( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta2.FlowSchema) (errs field.ErrorList) { + + // field flowcontrolv1beta2.FlowSchema.TypeMeta has no validation + // field flowcontrolv1beta2.FlowSchema.ObjectMeta has no validation + + { // field flowcontrolv1beta2.FlowSchema.Spec + fn := func( + fldPath *field.Path, + obj, oldObj *flowcontrolv1beta2.FlowSchemaSpec, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call the type's validation function + errs = append(errs, Validate_FlowSchemaSpec(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta2.FlowSchema) *flowcontrolv1beta2.FlowSchemaSpec { + return &oldObj.Spec + }) + errs = append(errs, fn(fldPath.Child("spec"), &obj.Spec, oldVal, oldObj != nil)...) + } + + // field flowcontrolv1beta2.FlowSchema.Status has no validation + return errs +} + +// Validate_FlowSchemaSpec validates an instance of FlowSchemaSpec according +// to declarative validation rules in the API schema. +func Validate_FlowSchemaSpec( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta2.FlowSchemaSpec) (errs field.ErrorList) { + + // field flowcontrolv1beta2.FlowSchemaSpec.PriorityLevelConfiguration has no validation + // field flowcontrolv1beta2.FlowSchemaSpec.MatchingPrecedence has no validation + // field flowcontrolv1beta2.FlowSchemaSpec.DistinguisherMethod has no validation + + { // field flowcontrolv1beta2.FlowSchemaSpec.Rules + fn := func( + fldPath *field.Path, + obj, oldObj []flowcontrolv1beta2.PolicyRulesWithSubjects, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalSlice(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // iterate the list and call the type's validation function + if e := validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_PolicyRulesWithSubjects); len(e) != 0 { + errs = append(errs, e...) + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta2.FlowSchemaSpec) []flowcontrolv1beta2.PolicyRulesWithSubjects { + return oldObj.Rules + }) + errs = append(errs, fn(fldPath.Child("rules"), obj.Rules, oldVal, oldObj != nil)...) + } + + return errs +} + // Validate_LimitResponse validates an instance of LimitResponse according // to declarative validation rules in the API schema. func Validate_LimitResponse( @@ -189,6 +284,50 @@ func Validate_LimitedPriorityLevelConfiguration( return errs } +// Validate_PolicyRulesWithSubjects validates an instance of PolicyRulesWithSubjects according +// to declarative validation rules in the API schema. +func Validate_PolicyRulesWithSubjects( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta2.PolicyRulesWithSubjects) (errs field.ErrorList) { + + { // field flowcontrolv1beta2.PolicyRulesWithSubjects.Subjects + fn := func( + fldPath *field.Path, + obj, oldObj []flowcontrolv1beta2.Subject, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.RequiredSlice(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // iterate the list and call the type's validation function + if e := validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_Subject); len(e) != 0 { + errs = append(errs, e...) + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta2.PolicyRulesWithSubjects) []flowcontrolv1beta2.Subject { + return oldObj.Subjects + }) + errs = append(errs, fn(fldPath.Child("subjects"), obj.Subjects, oldVal, oldObj != nil)...) + } + + // field flowcontrolv1beta2.PolicyRulesWithSubjects.ResourceRules has no validation + // field flowcontrolv1beta2.PolicyRulesWithSubjects.NonResourceRules has no validation + return errs +} + // Validate_PriorityLevelConfiguration validates an instance of PriorityLevelConfiguration according // to declarative validation rules in the API schema. func Validate_PriorityLevelConfiguration( @@ -383,3 +522,129 @@ func Validate_PriorityLevelConfigurationSpec( return errs } + +var unionMembershipFor_k8s_io_api_flowcontrol_v1beta2_Subject_ = validate.NewDiscriminatedUnionMembership("kind", validate.NewDiscriminatedUnionMember("user", "User")) + +// Validate_Subject validates an instance of Subject according +// to declarative validation rules in the API schema. +func Validate_Subject( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta2.Subject) (errs field.ErrorList) { + + if e := validate.DiscriminatedUnion(ctx, op, fldPath, obj, oldObj, unionMembershipFor_k8s_io_api_flowcontrol_v1beta2_Subject_, + func(obj *flowcontrolv1beta2.Subject) string { + if obj == nil { + return "" + } + return string(obj.Kind) + }, + func(obj *flowcontrolv1beta2.Subject) bool { + if obj == nil { + return false + } + return obj.User != nil + }); len(e) != 0 { + errs = append(errs, e...) + } + + { // field flowcontrolv1beta2.Subject.Kind + fn := func( + fldPath *field.Path, + obj, oldObj *flowcontrolv1beta2.SubjectKind, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if 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).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta2.Subject) *flowcontrolv1beta2.SubjectKind { + return &oldObj.Kind + }) + errs = append(errs, fn(fldPath.Child("kind"), &obj.Kind, oldVal, oldObj != nil)...) + } + + { // field flowcontrolv1beta2.Subject.User + fn := func( + fldPath *field.Path, + obj, oldObj *flowcontrolv1beta2.UserSubject, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_UserSubject(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta2.Subject) *flowcontrolv1beta2.UserSubject { + return oldObj.User + }) + errs = append(errs, fn(fldPath.Child("user"), obj.User, oldVal, oldObj != nil)...) + } + + // field flowcontrolv1beta2.Subject.Group has no validation + // field flowcontrolv1beta2.Subject.ServiceAccount has no validation + return errs +} + +// Validate_UserSubject validates an instance of UserSubject according +// to declarative validation rules in the API schema. +func Validate_UserSubject( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta2.UserSubject) (errs field.ErrorList) { + + { // field flowcontrolv1beta2.UserSubject.Name + fn := func( + fldPath *field.Path, + obj, oldObj *string, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if 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).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta2.UserSubject) *string { + return &oldObj.Name + }) + errs = append(errs, fn(fldPath.Child("name"), &obj.Name, oldVal, 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 f870786bd06..9741899bd24 100644 --- a/pkg/apis/flowcontrol/v1beta3/zz_generated.validations.go +++ b/pkg/apis/flowcontrol/v1beta3/zz_generated.validations.go @@ -39,6 +39,21 @@ 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 FlowSchema + scheme.AddValidationFunc( + (*flowcontrolv1beta3.FlowSchema)(nil), + func(ctx context.Context, op operation.Operation, obj, oldObj interface{}) field.ErrorList { + switch op.Request.SubresourcePath() { + case "/", "/status": + return Validate_FlowSchema( + ctx, op, nil, /* fldPath */ + obj.(*flowcontrolv1beta3.FlowSchema), + safe.Cast[*flowcontrolv1beta3.FlowSchema](oldObj)) + } + return field.ErrorList{ + field.InternalError(nil, fmt.Errorf("no validation found for %T, subresource: %v", obj, op.Request.SubresourcePath())), + } + }) // type PriorityLevelConfiguration scheme.AddValidationFunc( (*flowcontrolv1beta3.PriorityLevelConfiguration)(nil), @@ -57,6 +72,86 @@ func RegisterValidations(scheme *runtime.Scheme) error { return nil } +// Validate_FlowSchema validates an instance of FlowSchema according +// to declarative validation rules in the API schema. +func Validate_FlowSchema( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta3.FlowSchema) (errs field.ErrorList) { + + // field flowcontrolv1beta3.FlowSchema.TypeMeta has no validation + // field flowcontrolv1beta3.FlowSchema.ObjectMeta has no validation + + { // field flowcontrolv1beta3.FlowSchema.Spec + fn := func( + fldPath *field.Path, + obj, oldObj *flowcontrolv1beta3.FlowSchemaSpec, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call the type's validation function + errs = append(errs, Validate_FlowSchemaSpec(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta3.FlowSchema) *flowcontrolv1beta3.FlowSchemaSpec { + return &oldObj.Spec + }) + errs = append(errs, fn(fldPath.Child("spec"), &obj.Spec, oldVal, oldObj != nil)...) + } + + // field flowcontrolv1beta3.FlowSchema.Status has no validation + return errs +} + +// Validate_FlowSchemaSpec validates an instance of FlowSchemaSpec according +// to declarative validation rules in the API schema. +func Validate_FlowSchemaSpec( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta3.FlowSchemaSpec) (errs field.ErrorList) { + + // field flowcontrolv1beta3.FlowSchemaSpec.PriorityLevelConfiguration has no validation + // field flowcontrolv1beta3.FlowSchemaSpec.MatchingPrecedence has no validation + // field flowcontrolv1beta3.FlowSchemaSpec.DistinguisherMethod has no validation + + { // field flowcontrolv1beta3.FlowSchemaSpec.Rules + fn := func( + fldPath *field.Path, + obj, oldObj []flowcontrolv1beta3.PolicyRulesWithSubjects, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalSlice(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // iterate the list and call the type's validation function + if e := validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_PolicyRulesWithSubjects); len(e) != 0 { + errs = append(errs, e...) + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta3.FlowSchemaSpec) []flowcontrolv1beta3.PolicyRulesWithSubjects { + return oldObj.Rules + }) + errs = append(errs, fn(fldPath.Child("rules"), obj.Rules, oldVal, oldObj != nil)...) + } + + return errs +} + // Validate_LimitResponse validates an instance of LimitResponse according // to declarative validation rules in the API schema. func Validate_LimitResponse( @@ -189,6 +284,50 @@ func Validate_LimitedPriorityLevelConfiguration( return errs } +// Validate_PolicyRulesWithSubjects validates an instance of PolicyRulesWithSubjects according +// to declarative validation rules in the API schema. +func Validate_PolicyRulesWithSubjects( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta3.PolicyRulesWithSubjects) (errs field.ErrorList) { + + { // field flowcontrolv1beta3.PolicyRulesWithSubjects.Subjects + fn := func( + fldPath *field.Path, + obj, oldObj []flowcontrolv1beta3.Subject, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.RequiredSlice(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // iterate the list and call the type's validation function + if e := validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_Subject); len(e) != 0 { + errs = append(errs, e...) + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta3.PolicyRulesWithSubjects) []flowcontrolv1beta3.Subject { + return oldObj.Subjects + }) + errs = append(errs, fn(fldPath.Child("subjects"), obj.Subjects, oldVal, oldObj != nil)...) + } + + // field flowcontrolv1beta3.PolicyRulesWithSubjects.ResourceRules has no validation + // field flowcontrolv1beta3.PolicyRulesWithSubjects.NonResourceRules has no validation + return errs +} + // Validate_PriorityLevelConfiguration validates an instance of PriorityLevelConfiguration according // to declarative validation rules in the API schema. func Validate_PriorityLevelConfiguration( @@ -383,3 +522,129 @@ func Validate_PriorityLevelConfigurationSpec( return errs } + +var unionMembershipFor_k8s_io_api_flowcontrol_v1beta3_Subject_ = validate.NewDiscriminatedUnionMembership("kind", validate.NewDiscriminatedUnionMember("user", "User")) + +// Validate_Subject validates an instance of Subject according +// to declarative validation rules in the API schema. +func Validate_Subject( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta3.Subject) (errs field.ErrorList) { + + if e := validate.DiscriminatedUnion(ctx, op, fldPath, obj, oldObj, unionMembershipFor_k8s_io_api_flowcontrol_v1beta3_Subject_, + func(obj *flowcontrolv1beta3.Subject) string { + if obj == nil { + return "" + } + return string(obj.Kind) + }, + func(obj *flowcontrolv1beta3.Subject) bool { + if obj == nil { + return false + } + return obj.User != nil + }); len(e) != 0 { + errs = append(errs, e...) + } + + { // field flowcontrolv1beta3.Subject.Kind + fn := func( + fldPath *field.Path, + obj, oldObj *flowcontrolv1beta3.SubjectKind, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if 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).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta3.Subject) *flowcontrolv1beta3.SubjectKind { + return &oldObj.Kind + }) + errs = append(errs, fn(fldPath.Child("kind"), &obj.Kind, oldVal, oldObj != nil)...) + } + + { // field flowcontrolv1beta3.Subject.User + fn := func( + fldPath *field.Path, + obj, oldObj *flowcontrolv1beta3.UserSubject, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_UserSubject(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta3.Subject) *flowcontrolv1beta3.UserSubject { + return oldObj.User + }) + errs = append(errs, fn(fldPath.Child("user"), obj.User, oldVal, oldObj != nil)...) + } + + // field flowcontrolv1beta3.Subject.Group has no validation + // field flowcontrolv1beta3.Subject.ServiceAccount has no validation + return errs +} + +// Validate_UserSubject validates an instance of UserSubject according +// to declarative validation rules in the API schema. +func Validate_UserSubject( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *flowcontrolv1beta3.UserSubject) (errs field.ErrorList) { + + { // field flowcontrolv1beta3.UserSubject.Name + fn := func( + fldPath *field.Path, + obj, oldObj *string, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if 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).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *flowcontrolv1beta3.UserSubject) *string { + return &oldObj.Name + }) + errs = append(errs, fn(fldPath.Child("name"), &obj.Name, oldVal, oldObj != nil)...) + } + + return errs +} diff --git a/pkg/apis/flowcontrol/validation/validation.go b/pkg/apis/flowcontrol/validation/validation.go index d801f0e1382..c3da023dc9c 100644 --- a/pkg/apis/flowcontrol/validation/validation.go +++ b/pkg/apis/flowcontrol/validation/validation.go @@ -217,10 +217,10 @@ func ValidateServiceAccountSubject(subject *flowcontrol.ServiceAccountSubject, f func ValidateUserSubject(subject *flowcontrol.UserSubject, fldPath *field.Path) field.ErrorList { var allErrs field.ErrorList if subject == nil { - return append(allErrs, field.Required(fldPath, "user is required when subject kind is 'User'")) + return append(allErrs, field.Required(fldPath, "user is required when subject kind is 'User'").MarkCoveredByDeclarative()) } if len(subject.Name) == 0 { - allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) + allErrs = append(allErrs, field.Required(fldPath.Child("name"), "").MarkCoveredByDeclarative()) } return allErrs } diff --git a/pkg/apis/flowcontrol/validation/validation_test.go b/pkg/apis/flowcontrol/validation/validation_test.go index 9c3b2d305e7..4b7a5f8b1f3 100644 --- a/pkg/apis/flowcontrol/validation/validation_test.go +++ b/pkg/apis/flowcontrol/validation/validation_test.go @@ -192,7 +192,7 @@ func TestFlowSchemaValidation(t *testing.T) { }, expectedErrors: field.ErrorList{ field.Forbidden(field.NewPath("spec").Child("rules").Index(0).Child("subjects").Index(0).Child("serviceAccount"), "serviceAccount is forbidden when subject kind is not 'ServiceAccount'"), - field.Required(field.NewPath("spec").Child("rules").Index(0).Child("subjects").Index(0).Child("user"), "user is required when subject kind is 'User'"), + field.Required(field.NewPath("spec").Child("rules").Index(0).Child("subjects").Index(0).Child("user"), "user is required when subject kind is 'User'").MarkCoveredByDeclarative(), field.Forbidden(field.NewPath("spec").Child("rules").Index(0).Child("subjects").Index(0).Child("group"), "group is forbidden when subject kind is not 'Group'"), }, }, { diff --git a/pkg/registry/flowcontrol/flowschema/strategy.go b/pkg/registry/flowcontrol/flowschema/strategy.go index 6fe350b7a33..ddd499e5a3f 100644 --- a/pkg/registry/flowcontrol/flowschema/strategy.go +++ b/pkg/registry/flowcontrol/flowschema/strategy.go @@ -18,11 +18,11 @@ package flowschema import ( "context" + "k8s.io/apiserver/pkg/registry/rest" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/flowcontrol" diff --git a/staging/src/k8s.io/api/flowcontrol/v1/generated.proto b/staging/src/k8s.io/api/flowcontrol/v1/generated.proto index eaea7d6005b..cdb5dcbbac7 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1/generated.proto +++ b/staging/src/k8s.io/api/flowcontrol/v1/generated.proto @@ -146,6 +146,7 @@ message FlowSchemaSpec { // if it is an empty slice, there will be no requests matching the FlowSchema. // +listType=atomic // +optional + // +k8s:optional repeated PolicyRulesWithSubjects rules = 4; } @@ -286,6 +287,7 @@ message PolicyRulesWithSubjects { // A slice that includes both the system:authenticated and system:unauthenticated user groups matches every request. // +listType=atomic // Required. + // +k8s:required repeated Subject subjects = 1; // `resourceRules` is a slice of ResourcePolicyRules that identify matching requests according to their verb and the @@ -508,10 +510,14 @@ message Subject { // `kind` indicates which one of the other fields is non-empty. // Required // +unionDiscriminator + // +k8s:required optional string kind = 1; // `user` matches based on username. + // +unionMember=User + // +k8s:unionMember(memberName: "User") // +optional + // +k8s:optional optional UserSubject user = 2; // `group` matches based on user group name. @@ -527,6 +533,8 @@ message Subject { message UserSubject { // `name` is the username that matches, or "*" to match all usernames. // Required. + // +required + // +k8s:required optional string name = 1; } diff --git a/staging/src/k8s.io/api/flowcontrol/v1/types.go b/staging/src/k8s.io/api/flowcontrol/v1/types.go index 59d842b4f09..61b5fa91128 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1/types.go +++ b/staging/src/k8s.io/api/flowcontrol/v1/types.go @@ -163,6 +163,7 @@ type FlowSchemaSpec struct { // if it is an empty slice, there will be no requests matching the FlowSchema. // +listType=atomic // +optional + // +k8s:optional Rules []PolicyRulesWithSubjects `json:"rules,omitempty" protobuf:"bytes,4,rep,name=rules"` } @@ -208,6 +209,7 @@ type PolicyRulesWithSubjects struct { // A slice that includes both the system:authenticated and system:unauthenticated user groups matches every request. // +listType=atomic // Required. + // +k8s:required Subjects []Subject `json:"subjects" protobuf:"bytes,1,rep,name=subjects"` // `resourceRules` is a slice of ResourcePolicyRules that identify matching requests according to their verb and the // target resource. @@ -229,9 +231,13 @@ type Subject struct { // `kind` indicates which one of the other fields is non-empty. // Required // +unionDiscriminator + // +k8s:required Kind SubjectKind `json:"kind" protobuf:"bytes,1,opt,name=kind"` // `user` matches based on username. + // +unionMember=User + // +k8s:unionMember(memberName: "User") // +optional + // +k8s:optional User *UserSubject `json:"user,omitempty" protobuf:"bytes,2,opt,name=user"` // `group` matches based on user group name. // +optional @@ -255,6 +261,8 @@ const ( type UserSubject struct { // `name` is the username that matches, or "*" to match all usernames. // Required. + // +required + // +k8s:required Name string `json:"name" protobuf:"bytes,1,opt,name=name"` } diff --git a/staging/src/k8s.io/api/flowcontrol/v1beta1/generated.proto b/staging/src/k8s.io/api/flowcontrol/v1beta1/generated.proto index bbe4d2c66fb..f0e7204bc0e 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1beta1/generated.proto +++ b/staging/src/k8s.io/api/flowcontrol/v1beta1/generated.proto @@ -146,6 +146,7 @@ message FlowSchemaSpec { // if it is an empty slice, there will be no requests matching the FlowSchema. // +listType=atomic // +optional + // +k8s:optional repeated PolicyRulesWithSubjects rules = 4; } @@ -279,6 +280,7 @@ message PolicyRulesWithSubjects { // A slice that includes both the system:authenticated and system:unauthenticated user groups matches every request. // +listType=atomic // Required. + // +k8s:required repeated Subject subjects = 1; // `resourceRules` is a slice of ResourcePolicyRules that identify matching requests according to their verb and the @@ -499,10 +501,15 @@ message Subject { // `kind` indicates which one of the other fields is non-empty. // Required // +unionDiscriminator + // +k8s:unionDiscriminator + // +k8s:required optional string kind = 1; // `user` matches based on username. + // +unionMember=User + // +k8s:unionMember(memberName: "User") // +optional + // +k8s:optional optional UserSubject user = 2; // `group` matches based on user group name. @@ -518,6 +525,8 @@ message Subject { message UserSubject { // `name` is the username that matches, or "*" to match all usernames. // Required. + // +required + // +k8s:required optional string name = 1; } diff --git a/staging/src/k8s.io/api/flowcontrol/v1beta1/types.go b/staging/src/k8s.io/api/flowcontrol/v1beta1/types.go index 0eb1a9c506c..ba2493a66f6 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1beta1/types.go +++ b/staging/src/k8s.io/api/flowcontrol/v1beta1/types.go @@ -165,6 +165,7 @@ type FlowSchemaSpec struct { // if it is an empty slice, there will be no requests matching the FlowSchema. // +listType=atomic // +optional + // +k8s:optional Rules []PolicyRulesWithSubjects `json:"rules,omitempty" protobuf:"bytes,4,rep,name=rules"` } @@ -210,6 +211,7 @@ type PolicyRulesWithSubjects struct { // A slice that includes both the system:authenticated and system:unauthenticated user groups matches every request. // +listType=atomic // Required. + // +k8s:required Subjects []Subject `json:"subjects" protobuf:"bytes,1,rep,name=subjects"` // `resourceRules` is a slice of ResourcePolicyRules that identify matching requests according to their verb and the // target resource. @@ -231,9 +233,14 @@ type Subject struct { // `kind` indicates which one of the other fields is non-empty. // Required // +unionDiscriminator + // +k8s:unionDiscriminator + // +k8s:required Kind SubjectKind `json:"kind" protobuf:"bytes,1,opt,name=kind"` // `user` matches based on username. + // +unionMember=User + // +k8s:unionMember(memberName: "User") // +optional + // +k8s:optional User *UserSubject `json:"user,omitempty" protobuf:"bytes,2,opt,name=user"` // `group` matches based on user group name. // +optional @@ -257,6 +264,8 @@ const ( type UserSubject struct { // `name` is the username that matches, or "*" to match all usernames. // Required. + // +required + // +k8s:required Name string `json:"name" protobuf:"bytes,1,opt,name=name"` } diff --git a/staging/src/k8s.io/api/flowcontrol/v1beta2/generated.proto b/staging/src/k8s.io/api/flowcontrol/v1beta2/generated.proto index 83cdb5f169a..4c333c40754 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1beta2/generated.proto +++ b/staging/src/k8s.io/api/flowcontrol/v1beta2/generated.proto @@ -146,6 +146,7 @@ message FlowSchemaSpec { // if it is an empty slice, there will be no requests matching the FlowSchema. // +listType=atomic // +optional + // +k8s:optional repeated PolicyRulesWithSubjects rules = 4; } @@ -279,6 +280,7 @@ message PolicyRulesWithSubjects { // A slice that includes both the system:authenticated and system:unauthenticated user groups matches every request. // +listType=atomic // Required. + // +k8s:required repeated Subject subjects = 1; // `resourceRules` is a slice of ResourcePolicyRules that identify matching requests according to their verb and the @@ -499,10 +501,15 @@ message Subject { // `kind` indicates which one of the other fields is non-empty. // Required // +unionDiscriminator + // +k8s:unionDiscriminator + // +k8s:required optional string kind = 1; // `user` matches based on username. + // +unionMember=User + // +k8s:unionMember(memberName: "User") // +optional + // +k8s:optional optional UserSubject user = 2; // `group` matches based on user group name. @@ -518,6 +525,8 @@ message Subject { message UserSubject { // `name` is the username that matches, or "*" to match all usernames. // Required. + // +required + // +k8s:required optional string name = 1; } diff --git a/staging/src/k8s.io/api/flowcontrol/v1beta2/types.go b/staging/src/k8s.io/api/flowcontrol/v1beta2/types.go index 3ed36d1bfab..b00b9f6ecce 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1beta2/types.go +++ b/staging/src/k8s.io/api/flowcontrol/v1beta2/types.go @@ -165,6 +165,7 @@ type FlowSchemaSpec struct { // if it is an empty slice, there will be no requests matching the FlowSchema. // +listType=atomic // +optional + // +k8s:optional Rules []PolicyRulesWithSubjects `json:"rules,omitempty" protobuf:"bytes,4,rep,name=rules"` } @@ -210,6 +211,7 @@ type PolicyRulesWithSubjects struct { // A slice that includes both the system:authenticated and system:unauthenticated user groups matches every request. // +listType=atomic // Required. + // +k8s:required Subjects []Subject `json:"subjects" protobuf:"bytes,1,rep,name=subjects"` // `resourceRules` is a slice of ResourcePolicyRules that identify matching requests according to their verb and the // target resource. @@ -231,9 +233,14 @@ type Subject struct { // `kind` indicates which one of the other fields is non-empty. // Required // +unionDiscriminator + // +k8s:unionDiscriminator + // +k8s:required Kind SubjectKind `json:"kind" protobuf:"bytes,1,opt,name=kind"` // `user` matches based on username. + // +unionMember=User + // +k8s:unionMember(memberName: "User") // +optional + // +k8s:optional User *UserSubject `json:"user,omitempty" protobuf:"bytes,2,opt,name=user"` // `group` matches based on user group name. // +optional @@ -257,6 +264,8 @@ const ( type UserSubject struct { // `name` is the username that matches, or "*" to match all usernames. // Required. + // +required + // +k8s:required Name string `json:"name" protobuf:"bytes,1,opt,name=name"` } diff --git a/staging/src/k8s.io/api/flowcontrol/v1beta3/generated.proto b/staging/src/k8s.io/api/flowcontrol/v1beta3/generated.proto index 3260468a545..c91996563a5 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1beta3/generated.proto +++ b/staging/src/k8s.io/api/flowcontrol/v1beta3/generated.proto @@ -146,6 +146,7 @@ message FlowSchemaSpec { // if it is an empty slice, there will be no requests matching the FlowSchema. // +listType=atomic // +optional + // +k8s:optional repeated PolicyRulesWithSubjects rules = 4; } @@ -281,6 +282,7 @@ message PolicyRulesWithSubjects { // A slice that includes both the system:authenticated and system:unauthenticated user groups matches every request. // +listType=atomic // Required. + // +k8s:required repeated Subject subjects = 1; // `resourceRules` is a slice of ResourcePolicyRules that identify matching requests according to their verb and the @@ -503,10 +505,15 @@ message Subject { // `kind` indicates which one of the other fields is non-empty. // Required // +unionDiscriminator + // +k8s:unionDiscriminator + // +k8s:required optional string kind = 1; // `user` matches based on username. + // +unionMember=User + // +k8s:unionMember(memberName: "User") // +optional + // +k8s:optional optional UserSubject user = 2; // `group` matches based on user group name. @@ -522,6 +529,8 @@ message Subject { message UserSubject { // `name` is the username that matches, or "*" to match all usernames. // Required. + // +required + // +k8s:required optional string name = 1; } diff --git a/staging/src/k8s.io/api/flowcontrol/v1beta3/types.go b/staging/src/k8s.io/api/flowcontrol/v1beta3/types.go index dbecec56941..58a6eb734b2 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1beta3/types.go +++ b/staging/src/k8s.io/api/flowcontrol/v1beta3/types.go @@ -179,6 +179,7 @@ type FlowSchemaSpec struct { // if it is an empty slice, there will be no requests matching the FlowSchema. // +listType=atomic // +optional + // +k8s:optional Rules []PolicyRulesWithSubjects `json:"rules,omitempty" protobuf:"bytes,4,rep,name=rules"` } @@ -224,6 +225,7 @@ type PolicyRulesWithSubjects struct { // A slice that includes both the system:authenticated and system:unauthenticated user groups matches every request. // +listType=atomic // Required. + // +k8s:required Subjects []Subject `json:"subjects" protobuf:"bytes,1,rep,name=subjects"` // `resourceRules` is a slice of ResourcePolicyRules that identify matching requests according to their verb and the // target resource. @@ -245,9 +247,14 @@ type Subject struct { // `kind` indicates which one of the other fields is non-empty. // Required // +unionDiscriminator + // +k8s:unionDiscriminator + // +k8s:required Kind SubjectKind `json:"kind" protobuf:"bytes,1,opt,name=kind"` // `user` matches based on username. + // +unionMember=User + // +k8s:unionMember(memberName: "User") // +optional + // +k8s:optional User *UserSubject `json:"user,omitempty" protobuf:"bytes,2,opt,name=user"` // `group` matches based on user group name. // +optional @@ -271,6 +278,8 @@ const ( type UserSubject struct { // `name` is the username that matches, or "*" to match all usernames. // Required. + // +required + // +k8s:required Name string `json:"name" protobuf:"bytes,1,opt,name=name"` } diff --git a/test/declarative_validation/flowcontrol/flowschema/declarative_validation_test.go b/test/declarative_validation/flowcontrol/flowschema/declarative_validation_test.go new file mode 100644 index 00000000000..0a9ac19b93f --- /dev/null +++ b/test/declarative_validation/flowcontrol/flowschema/declarative_validation_test.go @@ -0,0 +1,152 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flowschema + +import ( + flowschema2 "k8s.io/kubernetes/pkg/registry/flowcontrol/flowschema" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/validation/field" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + apitesting "k8s.io/kubernetes/pkg/api/testing" + "k8s.io/kubernetes/pkg/apis/flowcontrol" +) + +func TestDeclarativeValidate(t *testing.T) { + for _, apiVersion := range apiVersions { + t.Run(apiVersion, func(t *testing.T) { + testDeclarativeValidate(t, apiVersion) + }) + } +} + +func testDeclarativeValidate(t *testing.T, apiVersion string) { + ctx := genericapirequest.WithRequestInfo(genericapirequest.NewDefaultContext(), &genericapirequest.RequestInfo{ + APIGroup: "flowcontrol.apiserver.k8s.io", + APIVersion: apiVersion, + Resource: "flowschemas", + IsResourceRequest: true, + Verb: "create", + }) + + testCases := map[string]struct { + input flowcontrol.FlowSchema + expectedErrs field.ErrorList + }{ + "valid": { + input: mkValidFlowSchema(), + }, + "user subject name is required": { + input: mkValidFlowSchema(tweakUserSubjectName("")), + expectedErrs: field.ErrorList{ + field.Required(field.NewPath("spec", "rules").Index(0).Child("subjects").Index(0).Child("user.name"), "").MarkCoveredByDeclarative(), + }, + }, + } + for k, tc := range testCases { + t.Run(k, func(t *testing.T) { + apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, flowschema2.Strategy, tc.expectedErrs) + }) + } +} + +func TestDeclarativeValidateUpdate(t *testing.T) { + for _, apiVersion := range apiVersions { + t.Run(apiVersion, func(t *testing.T) { + testDeclarativeValidateUpdate(t, apiVersion) + }) + } +} + +func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) { + testCases := map[string]struct { + oldObj flowcontrol.FlowSchema + updateObj flowcontrol.FlowSchema + expectedErrs field.ErrorList + }{ + "valid update": { + oldObj: mkValidFlowSchema(), + updateObj: mkValidFlowSchema(), + }, + "user subject name is required": { + updateObj: mkValidFlowSchema(tweakUserSubjectName("")), + expectedErrs: field.ErrorList{ + field.Required(field.NewPath("spec", "rules").Index(0).Child("subjects").Index(0).Child("user.name"), "").MarkCoveredByDeclarative(), + }, + }, + } + for k, tc := range testCases { + t.Run(k, func(t *testing.T) { + ctx := genericapirequest.WithRequestInfo(genericapirequest.NewDefaultContext(), &genericapirequest.RequestInfo{ + APIPrefix: "apis", + APIGroup: "flowcontrol.apiserver.k8s.io", + APIVersion: apiVersion, + Resource: "flowschemas", + Name: "valid-flow-schema", + IsResourceRequest: true, + Verb: "update", + }) + apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, flowschema2.Strategy, tc.expectedErrs) + }) + } +} + +func mkValidFlowSchema(tweaks ...func(obj *flowcontrol.FlowSchema)) flowcontrol.FlowSchema { + obj := flowcontrol.FlowSchema{ + ObjectMeta: metav1.ObjectMeta{ + Name: "valid-flow-schema", + }, + Spec: flowcontrol.FlowSchemaSpec{ + PriorityLevelConfiguration: flowcontrol.PriorityLevelConfigurationReference{ + Name: "system-leader-election", + }, + MatchingPrecedence: 1000, + Rules: []flowcontrol.PolicyRulesWithSubjects{ + { + Subjects: []flowcontrol.Subject{ + { + Kind: flowcontrol.SubjectKindUser, + User: &flowcontrol.UserSubject{ + Name: "system:kube-controller-manager", + }, + }, + }, + ResourceRules: []flowcontrol.ResourcePolicyRule{ + { + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{""}, + Resources: []string{"pods"}, + Namespaces: []string{"production", "staging"}, + }, + }, + }, + }, + }, + } + obj.ResourceVersion = "1" + for _, tweak := range tweaks { + tweak(&obj) + } + return obj +} + +func tweakUserSubjectName(name string) func(*flowcontrol.FlowSchema) { + return func(fs *flowcontrol.FlowSchema) { + fs.Spec.Rules[0].Subjects[0].User.Name = name + } +} diff --git a/test/declarative_validation/flowcontrol/flowschema/zz_generated.main_test.go b/test/declarative_validation/flowcontrol/flowschema/zz_generated.main_test.go new file mode 100644 index 00000000000..7f02b07c2a5 --- /dev/null +++ b/test/declarative_validation/flowcontrol/flowschema/zz_generated.main_test.go @@ -0,0 +1,43 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by validation-gen. DO NOT EDIT. + +package flowschema + +import ( + fmt "fmt" + os "os" + testing "testing" + + coverage "k8s.io/apimachinery/pkg/test/coverage" +) + +var apiVersions = []string{"v1", "v1beta1", "v1beta2", "v1beta3"} + +func TestMain(m *testing.M) { + code := m.Run() + if err := coverage.AssertDeclarativeCoverage(); err != nil { + fmt.Fprintln(os.Stderr, err) + if code == 0 { + code = 1 + } + } + os.Exit(code) +} diff --git a/test/declarative_validation/flowcontrol/flowschema/zz_generated.v1_test.go b/test/declarative_validation/flowcontrol/flowschema/zz_generated.v1_test.go new file mode 100644 index 00000000000..bc77c7e9424 --- /dev/null +++ b/test/declarative_validation/flowcontrol/flowschema/zz_generated.v1_test.go @@ -0,0 +1,47 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by validation-gen. DO NOT EDIT. + +package flowschema + +import ( + schema "k8s.io/apimachinery/pkg/runtime/schema" + coverage "k8s.io/apimachinery/pkg/test/coverage" +) + +func init() { + coverage.RegisterDeclaredRules( + schema.GroupVersionKind{Group: "flowcontrol.apiserver.k8s.io", Version: "v1", Kind: "FlowSchema"}, + coverage.FieldRules{ + "spec.rules[*].subjects": { + {ErrorType: "FieldValueRequired"}, + }, + "spec.rules[*].subjects[*]": { + {ErrorType: "FieldValueInvalid", Origin: "union"}, + }, + "spec.rules[*].subjects[*].kind": { + {ErrorType: "FieldValueRequired"}, + }, + "spec.rules[*].subjects[*].user.name": { + {ErrorType: "FieldValueRequired"}, + }, + }, + ) +} diff --git a/test/declarative_validation/flowcontrol/flowschema/zz_generated.v1beta1_test.go b/test/declarative_validation/flowcontrol/flowschema/zz_generated.v1beta1_test.go new file mode 100644 index 00000000000..4cf4c656aa8 --- /dev/null +++ b/test/declarative_validation/flowcontrol/flowschema/zz_generated.v1beta1_test.go @@ -0,0 +1,47 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by validation-gen. DO NOT EDIT. + +package flowschema + +import ( + schema "k8s.io/apimachinery/pkg/runtime/schema" + coverage "k8s.io/apimachinery/pkg/test/coverage" +) + +func init() { + coverage.RegisterDeclaredRules( + schema.GroupVersionKind{Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta1", Kind: "FlowSchema"}, + coverage.FieldRules{ + "spec.rules[*].subjects": { + {ErrorType: "FieldValueRequired"}, + }, + "spec.rules[*].subjects[*]": { + {ErrorType: "FieldValueInvalid", Origin: "union"}, + }, + "spec.rules[*].subjects[*].kind": { + {ErrorType: "FieldValueRequired"}, + }, + "spec.rules[*].subjects[*].user.name": { + {ErrorType: "FieldValueRequired"}, + }, + }, + ) +} diff --git a/test/declarative_validation/flowcontrol/flowschema/zz_generated.v1beta2_test.go b/test/declarative_validation/flowcontrol/flowschema/zz_generated.v1beta2_test.go new file mode 100644 index 00000000000..b561a3929be --- /dev/null +++ b/test/declarative_validation/flowcontrol/flowschema/zz_generated.v1beta2_test.go @@ -0,0 +1,47 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by validation-gen. DO NOT EDIT. + +package flowschema + +import ( + schema "k8s.io/apimachinery/pkg/runtime/schema" + coverage "k8s.io/apimachinery/pkg/test/coverage" +) + +func init() { + coverage.RegisterDeclaredRules( + schema.GroupVersionKind{Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta2", Kind: "FlowSchema"}, + coverage.FieldRules{ + "spec.rules[*].subjects": { + {ErrorType: "FieldValueRequired"}, + }, + "spec.rules[*].subjects[*]": { + {ErrorType: "FieldValueInvalid", Origin: "union"}, + }, + "spec.rules[*].subjects[*].kind": { + {ErrorType: "FieldValueRequired"}, + }, + "spec.rules[*].subjects[*].user.name": { + {ErrorType: "FieldValueRequired"}, + }, + }, + ) +} diff --git a/test/declarative_validation/flowcontrol/flowschema/zz_generated.v1beta3_test.go b/test/declarative_validation/flowcontrol/flowschema/zz_generated.v1beta3_test.go new file mode 100644 index 00000000000..aa8b35e9d51 --- /dev/null +++ b/test/declarative_validation/flowcontrol/flowschema/zz_generated.v1beta3_test.go @@ -0,0 +1,47 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by validation-gen. DO NOT EDIT. + +package flowschema + +import ( + schema "k8s.io/apimachinery/pkg/runtime/schema" + coverage "k8s.io/apimachinery/pkg/test/coverage" +) + +func init() { + coverage.RegisterDeclaredRules( + schema.GroupVersionKind{Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta3", Kind: "FlowSchema"}, + coverage.FieldRules{ + "spec.rules[*].subjects": { + {ErrorType: "FieldValueRequired"}, + }, + "spec.rules[*].subjects[*]": { + {ErrorType: "FieldValueInvalid", Origin: "union"}, + }, + "spec.rules[*].subjects[*].kind": { + {ErrorType: "FieldValueRequired"}, + }, + "spec.rules[*].subjects[*].user.name": { + {ErrorType: "FieldValueRequired"}, + }, + }, + ) +}