feat: add PriorityLevelConfigurationSpec declarative validation discriminator tags

This commit is contained in:
Aaron Prindle
2026-03-12 13:00:57 -07:00
parent 865ef0ca3e
commit 595da7826c
15 changed files with 885 additions and 10 deletions

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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)...)
}

View File

@@ -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{

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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"`
}

View File

@@ -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;
}

View File

@@ -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"`
}

View File

@@ -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;
}

View File

@@ -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"`
}

View File

@@ -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;
}

View File

@@ -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"`
}