mirror of
https://github.com/kubernetes/kubernetes.git
synced 2026-06-09 08:55:55 -04:00
Use eachKey DV in DRA resources.
This commit is contained in:
parent
d915ef1660
commit
8f0a6583ca
13 changed files with 370 additions and 21 deletions
86
pkg/apis/resource/v1/zz_generated.validations.go
generated
86
pkg/apis/resource/v1/zz_generated.validations.go
generated
|
|
@ -193,6 +193,34 @@ func Validate_AllocationResult(ctx context.Context, op operation.Operation, fldP
|
|||
return errs
|
||||
}
|
||||
|
||||
// Validate_CounterSet validates an instance of CounterSet according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_CounterSet(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1.CounterSet) (errs field.ErrorList) {
|
||||
// field resourcev1.CounterSet.Name has no validation
|
||||
|
||||
// field resourcev1.CounterSet.Counters
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj map[string]resourcev1.Counter) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// call field-attached validations
|
||||
earlyReturn := false
|
||||
if e := validate.RequiredMap(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
|
||||
errs = append(errs, e...)
|
||||
earlyReturn = true
|
||||
}
|
||||
if earlyReturn {
|
||||
return // do not proceed
|
||||
}
|
||||
errs = append(errs, validate.EachMapKey(ctx, op, fldPath, obj, oldObj, validate.ShortName)...)
|
||||
return
|
||||
}(fldPath.Child("counters"), obj.Counters, safe.Field(oldObj, func(oldObj *resourcev1.CounterSet) map[string]resourcev1.Counter { return oldObj.Counters }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_Device validates an instance of Device according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_Device(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1.Device) (errs field.ErrorList) {
|
||||
|
|
@ -213,7 +241,19 @@ func Validate_Device(ctx context.Context, op operation.Operation, fldPath *field
|
|||
}))...)
|
||||
|
||||
// field resourcev1.Device.Capacity has no validation
|
||||
// field resourcev1.Device.ConsumesCounters has no validation
|
||||
|
||||
// field resourcev1.Device.ConsumesCounters
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []resourcev1.DeviceCounterConsumption) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// iterate the list and call the type's validation function
|
||||
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_DeviceCounterConsumption)...)
|
||||
return
|
||||
}(fldPath.Child("consumesCounters"), obj.ConsumesCounters, safe.Field(oldObj, func(oldObj *resourcev1.Device) []resourcev1.DeviceCounterConsumption { return oldObj.ConsumesCounters }))...)
|
||||
|
||||
// field resourcev1.Device.NodeName has no validation
|
||||
// field resourcev1.Device.NodeSelector has no validation
|
||||
// field resourcev1.Device.AllNodes has no validation
|
||||
|
|
@ -811,6 +851,36 @@ func Validate_DeviceConstraint(ctx context.Context, op operation.Operation, fldP
|
|||
return errs
|
||||
}
|
||||
|
||||
// Validate_DeviceCounterConsumption validates an instance of DeviceCounterConsumption according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_DeviceCounterConsumption(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1.DeviceCounterConsumption) (errs field.ErrorList) {
|
||||
// field resourcev1.DeviceCounterConsumption.CounterSet has no validation
|
||||
|
||||
// field resourcev1.DeviceCounterConsumption.Counters
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj map[string]resourcev1.Counter) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// call field-attached validations
|
||||
earlyReturn := false
|
||||
if e := validate.RequiredMap(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
|
||||
errs = append(errs, e...)
|
||||
earlyReturn = true
|
||||
}
|
||||
if earlyReturn {
|
||||
return // do not proceed
|
||||
}
|
||||
errs = append(errs, validate.EachMapKey(ctx, op, fldPath, obj, oldObj, validate.ShortName)...)
|
||||
return
|
||||
}(fldPath.Child("counters"), obj.Counters, safe.Field(oldObj, func(oldObj *resourcev1.DeviceCounterConsumption) map[string]resourcev1.Counter {
|
||||
return oldObj.Counters
|
||||
}))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_DeviceRequest validates an instance of DeviceRequest according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_DeviceRequest(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1.DeviceRequest) (errs field.ErrorList) {
|
||||
|
|
@ -1615,6 +1685,18 @@ func Validate_ResourceSliceSpec(ctx context.Context, op operation.Operation, fld
|
|||
}(fldPath.Child("devices"), obj.Devices, safe.Field(oldObj, func(oldObj *resourcev1.ResourceSliceSpec) []resourcev1.Device { return oldObj.Devices }))...)
|
||||
|
||||
// field resourcev1.ResourceSliceSpec.PerDeviceNodeSelection has no validation
|
||||
// field resourcev1.ResourceSliceSpec.SharedCounters has no validation
|
||||
|
||||
// field resourcev1.ResourceSliceSpec.SharedCounters
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []resourcev1.CounterSet) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// iterate the list and call the type's validation function
|
||||
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_CounterSet)...)
|
||||
return
|
||||
}(fldPath.Child("sharedCounters"), obj.SharedCounters, safe.Field(oldObj, func(oldObj *resourcev1.ResourceSliceSpec) []resourcev1.CounterSet { return oldObj.SharedCounters }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,7 +213,21 @@ func Validate_BasicDevice(ctx context.Context, op operation.Operation, fldPath *
|
|||
}))...)
|
||||
|
||||
// field resourcev1beta1.BasicDevice.Capacity has no validation
|
||||
// field resourcev1beta1.BasicDevice.ConsumesCounters has no validation
|
||||
|
||||
// field resourcev1beta1.BasicDevice.ConsumesCounters
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []resourcev1beta1.DeviceCounterConsumption) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// iterate the list and call the type's validation function
|
||||
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_DeviceCounterConsumption)...)
|
||||
return
|
||||
}(fldPath.Child("consumesCounters"), obj.ConsumesCounters, safe.Field(oldObj, func(oldObj *resourcev1beta1.BasicDevice) []resourcev1beta1.DeviceCounterConsumption {
|
||||
return oldObj.ConsumesCounters
|
||||
}))...)
|
||||
|
||||
// field resourcev1beta1.BasicDevice.NodeName has no validation
|
||||
// field resourcev1beta1.BasicDevice.NodeSelector has no validation
|
||||
// field resourcev1beta1.BasicDevice.AllNodes has no validation
|
||||
|
|
@ -280,6 +294,34 @@ func Validate_BasicDevice(ctx context.Context, op operation.Operation, fldPath *
|
|||
return errs
|
||||
}
|
||||
|
||||
// Validate_CounterSet validates an instance of CounterSet according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_CounterSet(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta1.CounterSet) (errs field.ErrorList) {
|
||||
// field resourcev1beta1.CounterSet.Name has no validation
|
||||
|
||||
// field resourcev1beta1.CounterSet.Counters
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj map[string]resourcev1beta1.Counter) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// call field-attached validations
|
||||
earlyReturn := false
|
||||
if e := validate.RequiredMap(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
|
||||
errs = append(errs, e...)
|
||||
earlyReturn = true
|
||||
}
|
||||
if earlyReturn {
|
||||
return // do not proceed
|
||||
}
|
||||
errs = append(errs, validate.EachMapKey(ctx, op, fldPath, obj, oldObj, validate.ShortName)...)
|
||||
return
|
||||
}(fldPath.Child("counters"), obj.Counters, safe.Field(oldObj, func(oldObj *resourcev1beta1.CounterSet) map[string]resourcev1beta1.Counter { return oldObj.Counters }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_Device validates an instance of Device according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_Device(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta1.Device) (errs field.ErrorList) {
|
||||
|
|
@ -839,6 +881,36 @@ func Validate_DeviceConstraint(ctx context.Context, op operation.Operation, fldP
|
|||
return errs
|
||||
}
|
||||
|
||||
// Validate_DeviceCounterConsumption validates an instance of DeviceCounterConsumption according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_DeviceCounterConsumption(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta1.DeviceCounterConsumption) (errs field.ErrorList) {
|
||||
// field resourcev1beta1.DeviceCounterConsumption.CounterSet has no validation
|
||||
|
||||
// field resourcev1beta1.DeviceCounterConsumption.Counters
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj map[string]resourcev1beta1.Counter) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// call field-attached validations
|
||||
earlyReturn := false
|
||||
if e := validate.RequiredMap(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
|
||||
errs = append(errs, e...)
|
||||
earlyReturn = true
|
||||
}
|
||||
if earlyReturn {
|
||||
return // do not proceed
|
||||
}
|
||||
errs = append(errs, validate.EachMapKey(ctx, op, fldPath, obj, oldObj, validate.ShortName)...)
|
||||
return
|
||||
}(fldPath.Child("counters"), obj.Counters, safe.Field(oldObj, func(oldObj *resourcev1beta1.DeviceCounterConsumption) map[string]resourcev1beta1.Counter {
|
||||
return oldObj.Counters
|
||||
}))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_DeviceRequest validates an instance of DeviceRequest according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_DeviceRequest(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta1.DeviceRequest) (errs field.ErrorList) {
|
||||
|
|
@ -1647,6 +1719,20 @@ func Validate_ResourceSliceSpec(ctx context.Context, op operation.Operation, fld
|
|||
}(fldPath.Child("devices"), obj.Devices, safe.Field(oldObj, func(oldObj *resourcev1beta1.ResourceSliceSpec) []resourcev1beta1.Device { return oldObj.Devices }))...)
|
||||
|
||||
// field resourcev1beta1.ResourceSliceSpec.PerDeviceNodeSelection has no validation
|
||||
// field resourcev1beta1.ResourceSliceSpec.SharedCounters has no validation
|
||||
|
||||
// field resourcev1beta1.ResourceSliceSpec.SharedCounters
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []resourcev1beta1.CounterSet) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// iterate the list and call the type's validation function
|
||||
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_CounterSet)...)
|
||||
return
|
||||
}(fldPath.Child("sharedCounters"), obj.SharedCounters, safe.Field(oldObj, func(oldObj *resourcev1beta1.ResourceSliceSpec) []resourcev1beta1.CounterSet {
|
||||
return oldObj.SharedCounters
|
||||
}))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,6 +195,34 @@ func Validate_AllocationResult(ctx context.Context, op operation.Operation, fldP
|
|||
return errs
|
||||
}
|
||||
|
||||
// Validate_CounterSet validates an instance of CounterSet according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_CounterSet(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta2.CounterSet) (errs field.ErrorList) {
|
||||
// field resourcev1beta2.CounterSet.Name has no validation
|
||||
|
||||
// field resourcev1beta2.CounterSet.Counters
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj map[string]resourcev1beta2.Counter) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// call field-attached validations
|
||||
earlyReturn := false
|
||||
if e := validate.RequiredMap(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
|
||||
errs = append(errs, e...)
|
||||
earlyReturn = true
|
||||
}
|
||||
if earlyReturn {
|
||||
return // do not proceed
|
||||
}
|
||||
errs = append(errs, validate.EachMapKey(ctx, op, fldPath, obj, oldObj, validate.ShortName)...)
|
||||
return
|
||||
}(fldPath.Child("counters"), obj.Counters, safe.Field(oldObj, func(oldObj *resourcev1beta2.CounterSet) map[string]resourcev1beta2.Counter { return oldObj.Counters }))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_Device validates an instance of Device according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_Device(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta2.Device) (errs field.ErrorList) {
|
||||
|
|
@ -215,7 +243,21 @@ func Validate_Device(ctx context.Context, op operation.Operation, fldPath *field
|
|||
}))...)
|
||||
|
||||
// field resourcev1beta2.Device.Capacity has no validation
|
||||
// field resourcev1beta2.Device.ConsumesCounters has no validation
|
||||
|
||||
// field resourcev1beta2.Device.ConsumesCounters
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []resourcev1beta2.DeviceCounterConsumption) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// iterate the list and call the type's validation function
|
||||
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_DeviceCounterConsumption)...)
|
||||
return
|
||||
}(fldPath.Child("consumesCounters"), obj.ConsumesCounters, safe.Field(oldObj, func(oldObj *resourcev1beta2.Device) []resourcev1beta2.DeviceCounterConsumption {
|
||||
return oldObj.ConsumesCounters
|
||||
}))...)
|
||||
|
||||
// field resourcev1beta2.Device.NodeName has no validation
|
||||
// field resourcev1beta2.Device.NodeSelector has no validation
|
||||
// field resourcev1beta2.Device.AllNodes has no validation
|
||||
|
|
@ -821,6 +863,36 @@ func Validate_DeviceConstraint(ctx context.Context, op operation.Operation, fldP
|
|||
return errs
|
||||
}
|
||||
|
||||
// Validate_DeviceCounterConsumption validates an instance of DeviceCounterConsumption according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_DeviceCounterConsumption(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta2.DeviceCounterConsumption) (errs field.ErrorList) {
|
||||
// field resourcev1beta2.DeviceCounterConsumption.CounterSet has no validation
|
||||
|
||||
// field resourcev1beta2.DeviceCounterConsumption.Counters
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj map[string]resourcev1beta2.Counter) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// call field-attached validations
|
||||
earlyReturn := false
|
||||
if e := validate.RequiredMap(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
|
||||
errs = append(errs, e...)
|
||||
earlyReturn = true
|
||||
}
|
||||
if earlyReturn {
|
||||
return // do not proceed
|
||||
}
|
||||
errs = append(errs, validate.EachMapKey(ctx, op, fldPath, obj, oldObj, validate.ShortName)...)
|
||||
return
|
||||
}(fldPath.Child("counters"), obj.Counters, safe.Field(oldObj, func(oldObj *resourcev1beta2.DeviceCounterConsumption) map[string]resourcev1beta2.Counter {
|
||||
return oldObj.Counters
|
||||
}))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate_DeviceRequest validates an instance of DeviceRequest according
|
||||
// to declarative validation rules in the API schema.
|
||||
func Validate_DeviceRequest(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *resourcev1beta2.DeviceRequest) (errs field.ErrorList) {
|
||||
|
|
@ -1649,6 +1721,20 @@ func Validate_ResourceSliceSpec(ctx context.Context, op operation.Operation, fld
|
|||
}(fldPath.Child("devices"), obj.Devices, safe.Field(oldObj, func(oldObj *resourcev1beta2.ResourceSliceSpec) []resourcev1beta2.Device { return oldObj.Devices }))...)
|
||||
|
||||
// field resourcev1beta2.ResourceSliceSpec.PerDeviceNodeSelection has no validation
|
||||
// field resourcev1beta2.ResourceSliceSpec.SharedCounters has no validation
|
||||
|
||||
// field resourcev1beta2.ResourceSliceSpec.SharedCounters
|
||||
errs = append(errs,
|
||||
func(fldPath *field.Path, obj, oldObj []resourcev1beta2.CounterSet) (errs field.ErrorList) {
|
||||
// don't revalidate unchanged data
|
||||
if op.Type == operation.Update && equality.Semantic.DeepEqual(obj, oldObj) {
|
||||
return nil
|
||||
}
|
||||
// iterate the list and call the type's validation function
|
||||
errs = append(errs, validate.EachSliceVal(ctx, op, fldPath, obj, oldObj, nil, nil, Validate_CounterSet)...)
|
||||
return
|
||||
}(fldPath.Child("sharedCounters"), obj.SharedCounters, safe.Field(oldObj, func(oldObj *resourcev1beta2.ResourceSliceSpec) []resourcev1beta2.CounterSet {
|
||||
return oldObj.SharedCounters
|
||||
}))...)
|
||||
|
||||
return errs
|
||||
}
|
||||
|
|
|
|||
|
|
@ -751,7 +751,7 @@ func validateCounterSet(counterSet resource.CounterSet, fldPath *field.Path) fie
|
|||
} else {
|
||||
// The size limit is enforced for across all sets by the caller.
|
||||
allErrs = append(allErrs, validateMap(counterSet.Counters, -1, validation.DNS1123LabelMaxLength,
|
||||
validateCounterName, validateDeviceCounter, fldPath.Child("counters"))...)
|
||||
validateCounterName, validateDeviceCounter, fldPath.Child("counters"), keysCovered)...)
|
||||
}
|
||||
|
||||
return allErrs
|
||||
|
|
@ -876,7 +876,7 @@ func validateDeviceCounterConsumption(deviceCounterConsumption resource.DeviceCo
|
|||
} else {
|
||||
// The size limit is enforced for the entire device.
|
||||
allErrs = append(allErrs, validateMap(deviceCounterConsumption.Counters, -1, validation.DNS1123LabelMaxLength,
|
||||
validateCounterName, validateDeviceCounter, fldPath.Child("counters"))...)
|
||||
validateCounterName, validateDeviceCounter, fldPath.Child("counters"), keysCovered)...)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
|
@ -1142,6 +1142,8 @@ const (
|
|||
sizeCovered
|
||||
// The uniqueness check is covered by declarative validation.
|
||||
uniquenessCovered
|
||||
// key validation is covered by declarative validation.
|
||||
keysCovered
|
||||
)
|
||||
|
||||
// validateSlice ensures that a slice does not exceed a certain maximum size
|
||||
|
|
@ -1210,14 +1212,19 @@ func quantityKey(item apiresource.Quantity) string {
|
|||
// small limit gets increased because it is okay to include more details.
|
||||
// This is not used for validation of keys, which has to be done by
|
||||
// the callback function.
|
||||
func validateMap[K ~string, T any](m map[K]T, maxSize, truncateKeyLen int, validateKey func(K, *field.Path) field.ErrorList, validateItem func(T, *field.Path) field.ErrorList, fldPath *field.Path) field.ErrorList {
|
||||
func validateMap[K ~string, T any](m map[K]T, maxSize, truncateKeyLen int, validateKey func(K, *field.Path) field.ErrorList, validateItem func(T, *field.Path) field.ErrorList, fldPath *field.Path, opts ...validationOption) field.ErrorList {
|
||||
var allErrs field.ErrorList
|
||||
if maxSize >= 0 && len(m) > maxSize {
|
||||
allErrs = append(allErrs, field.TooMany(fldPath, len(m), maxSize))
|
||||
}
|
||||
for key, item := range m {
|
||||
keyPath := fldPath.Key(truncateIfTooLong(string(key), truncateKeyLen))
|
||||
allErrs = append(allErrs, validateKey(key, keyPath)...)
|
||||
|
||||
keyValidationErrors := validateKey(key, fldPath)
|
||||
if slices.Contains(opts, keysCovered) {
|
||||
keyValidationErrors = keyValidationErrors.MarkCoveredByDeclarative()
|
||||
}
|
||||
allErrs = append(allErrs, keyValidationErrors...)
|
||||
allErrs = append(allErrs, validateItem(item, keyPath)...)
|
||||
}
|
||||
return allErrs
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ func TestValidateResourceSlice(t *testing.T) {
|
|||
},
|
||||
"bad-attribute": {
|
||||
wantFailures: field.ErrorList{
|
||||
field.Invalid(field.NewPath("spec", "devices").Index(1).Child("attributes").Key(badName), badName, "a valid C identifier must start with alphabetic character or '_', followed by a string of alphanumeric characters or '_' (e.g. 'my_name', or 'MY_NAME', or 'MyName', regex used for validation is '[A-Za-z_][A-Za-z0-9_]*')"),
|
||||
field.Invalid(field.NewPath("spec", "devices").Index(1).Child("attributes"), badName, "a valid C identifier must start with alphabetic character or '_', followed by a string of alphanumeric characters or '_' (e.g. 'my_name', or 'MY_NAME', or 'MyName', regex used for validation is '[A-Za-z_][A-Za-z0-9_]*')"),
|
||||
field.Invalid(field.NewPath("spec", "devices").Index(1).Child("attributes").Key(badName), "", "exactly one value must be specified").MarkCoveredByDeclarative(),
|
||||
field.Invalid(field.NewPath("spec", "devices").Index(2).Child("attributes").Key(goodName), resourceapi.DeviceAttribute{StringValue: ptr.To("x"), VersionValue: ptr.To("1.2.3")}, "exactly one value must be specified").MarkCoveredByDeclarative(),
|
||||
field.Invalid(field.NewPath("spec", "devices").Index(3).Child("attributes").Key(goodName).Child("version"), strings.Repeat("x", resourceapi.DeviceAttributeMaxValueLength+1), "must be a string compatible with semver.org spec 2.0.0"),
|
||||
|
|
@ -371,8 +371,8 @@ func TestValidateResourceSlice(t *testing.T) {
|
|||
},
|
||||
"bad-attribute-c-identifier": {
|
||||
wantFailures: field.ErrorList{
|
||||
field.TooLongMaxLength(field.NewPath("spec", "devices").Index(1).Child("attributes").Key(strings.Repeat(".", resourceapi.DeviceMaxIDLength+1)), strings.Repeat(".", resourceapi.DeviceMaxIDLength+1), resourceapi.DeviceMaxIDLength),
|
||||
field.Invalid(field.NewPath("spec", "devices").Index(1).Child("attributes").Key(strings.Repeat(".", resourceapi.DeviceMaxIDLength+1)), strings.Repeat(".", resourceapi.DeviceMaxIDLength+1), "a valid C identifier must start with alphabetic character or '_', followed by a string of alphanumeric characters or '_' (e.g. 'my_name', or 'MY_NAME', or 'MyName', regex used for validation is '[A-Za-z_][A-Za-z0-9_]*')"),
|
||||
field.TooLongMaxLength(field.NewPath("spec", "devices").Index(1).Child("attributes"), strings.Repeat(".", resourceapi.DeviceMaxIDLength+1), resourceapi.DeviceMaxIDLength),
|
||||
field.Invalid(field.NewPath("spec", "devices").Index(1).Child("attributes"), strings.Repeat(".", resourceapi.DeviceMaxIDLength+1), "a valid C identifier must start with alphabetic character or '_', followed by a string of alphanumeric characters or '_' (e.g. 'my_name', or 'MY_NAME', or 'MyName', regex used for validation is '[A-Za-z_][A-Za-z0-9_]*')"),
|
||||
},
|
||||
slice: func() *resourceapi.ResourceSlice {
|
||||
slice := testResourceSlice(goodName, goodName, goodName, 2)
|
||||
|
|
@ -384,8 +384,8 @@ func TestValidateResourceSlice(t *testing.T) {
|
|||
},
|
||||
"bad-attribute-domain": {
|
||||
wantFailures: field.ErrorList{
|
||||
field.TooLong(field.NewPath("spec", "devices").Index(1).Child("attributes").Key(strings.Repeat("_", resourceapi.DeviceMaxDomainLength+1)+"/y"), strings.Repeat("_", resourceapi.DeviceMaxDomainLength+1), resourceapi.DeviceMaxDomainLength),
|
||||
field.Invalid(field.NewPath("spec", "devices").Index(1).Child("attributes").Key(strings.Repeat("_", resourceapi.DeviceMaxDomainLength+1)+"/y"), strings.Repeat("_", resourceapi.DeviceMaxDomainLength+1), "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')"),
|
||||
field.TooLong(field.NewPath("spec", "devices").Index(1).Child("attributes"), strings.Repeat("_", resourceapi.DeviceMaxDomainLength+1), resourceapi.DeviceMaxDomainLength),
|
||||
field.Invalid(field.NewPath("spec", "devices").Index(1).Child("attributes"), strings.Repeat("_", resourceapi.DeviceMaxDomainLength+1), "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')"),
|
||||
},
|
||||
slice: func() *resourceapi.ResourceSlice {
|
||||
slice := testResourceSlice(goodName, goodName, goodName, 2)
|
||||
|
|
@ -397,8 +397,8 @@ func TestValidateResourceSlice(t *testing.T) {
|
|||
},
|
||||
"bad-key-too-long": {
|
||||
wantFailures: field.ErrorList{
|
||||
field.TooLong(field.NewPath("spec", "devices").Index(1).Child("attributes").Key("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxx/yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"), strings.Repeat("x", resourceapi.DeviceMaxDomainLength+1), resourceapi.DeviceMaxDomainLength),
|
||||
field.TooLongMaxLength(field.NewPath("spec", "devices").Index(1).Child("attributes").Key("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxx/yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"), strings.Repeat("y", resourceapi.DeviceMaxIDLength+1), resourceapi.DeviceMaxIDLength),
|
||||
field.TooLong(field.NewPath("spec", "devices").Index(1).Child("attributes"), strings.Repeat("x", resourceapi.DeviceMaxDomainLength+1), resourceapi.DeviceMaxDomainLength),
|
||||
field.TooLongMaxLength(field.NewPath("spec", "devices").Index(1).Child("attributes"), strings.Repeat("y", resourceapi.DeviceMaxIDLength+1), resourceapi.DeviceMaxIDLength),
|
||||
},
|
||||
slice: func() *resourceapi.ResourceSlice {
|
||||
slice := testResourceSlice(goodName, goodName, goodName, 2)
|
||||
|
|
@ -410,8 +410,8 @@ func TestValidateResourceSlice(t *testing.T) {
|
|||
},
|
||||
"bad-attribute-empty-domain-and-c-identifier": {
|
||||
wantFailures: field.ErrorList{
|
||||
field.Required(field.NewPath("spec", "devices").Index(1).Child("attributes").Key("/"), "the domain must not be empty"),
|
||||
field.Required(field.NewPath("spec", "devices").Index(1).Child("attributes").Key("/"), "the name must not be empty"),
|
||||
field.Required(field.NewPath("spec", "devices").Index(1).Child("attributes"), "the domain must not be empty"),
|
||||
field.Required(field.NewPath("spec", "devices").Index(1).Child("attributes"), "the name must not be empty"),
|
||||
},
|
||||
slice: func() *resourceapi.ResourceSlice {
|
||||
slice := testResourceSlice(goodName, goodName, goodName, 2)
|
||||
|
|
@ -663,7 +663,7 @@ func TestValidateResourceSlice(t *testing.T) {
|
|||
},
|
||||
"bad-countername-shared-counters": {
|
||||
wantFailures: field.ErrorList{
|
||||
field.Invalid(field.NewPath("spec", "sharedCounters").Index(0).Child("counters").Key(badName), badName, "a lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?')"),
|
||||
field.Invalid(field.NewPath("spec", "sharedCounters").Index(0).Child("counters"), badName, "a lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?')").MarkCoveredByDeclarative(),
|
||||
},
|
||||
slice: func() *resourceapi.ResourceSlice {
|
||||
slice := testResourceSlice(goodName, goodName, driverName, 1)
|
||||
|
|
|
|||
|
|
@ -122,6 +122,27 @@ func TestDeclarativeValidate(t *testing.T) {
|
|||
field.Invalid(field.NewPath("spec", "devices").Index(0).Child("attributes").Key("test.io/multiple"), "", ""),
|
||||
},
|
||||
},
|
||||
// spec.sharedCounters.counters
|
||||
"invalid: shared counter key with uppercase": {
|
||||
input: mkResourceSlice(tweakSharedCounter("InvalidKey")),
|
||||
expectedErrs: field.ErrorList{
|
||||
field.Invalid(field.NewPath("spec", "sharedCounters").Index(0).Child("counters"), "InvalidKey", "").WithOrigin("format=k8s-short-name"),
|
||||
},
|
||||
},
|
||||
"valid: shared counter key": {
|
||||
input: mkResourceSlice(tweakSharedCounter("valid-key")),
|
||||
},
|
||||
// spec.devices.consumesCounters.counters
|
||||
"invalid: device counter key with uppercase": {
|
||||
input: mkResourceSlice(tweakSharedCounter("InvalidKey"), tweakDeviceCounter("InvalidKey")),
|
||||
expectedErrs: field.ErrorList{
|
||||
field.Invalid(field.NewPath("spec", "sharedCounters").Index(0).Child("counters"), "InvalidKey", "").WithOrigin("format=k8s-short-name"),
|
||||
field.Invalid(field.NewPath("spec", "devices").Index(0).Child("consumesCounters").Index(0).Child("counters"), "InvalidKey", "").WithOrigin("format=k8s-short-name"),
|
||||
},
|
||||
},
|
||||
"valid: device counter key": {
|
||||
input: mkResourceSlice(tweakSharedCounter("valid-key"), tweakDeviceCounter("valid-key")),
|
||||
},
|
||||
// TODO: Add more test cases
|
||||
}
|
||||
|
||||
|
|
@ -212,6 +233,23 @@ func TestDeclarativeValidateUpdate(t *testing.T) {
|
|||
field.Invalid(field.NewPath("spec", "devices").Index(0).Child("attributes").Key("test.io/multiple"), "", "may have only one of the following fields set: bool, int, string, version"),
|
||||
},
|
||||
},
|
||||
// spec.sharedCounters.counters
|
||||
"invalid update: shared counter key with uppercase": {
|
||||
old: mkResourceSlice(),
|
||||
update: mkResourceSlice(tweakSharedCounter("InvalidKey")),
|
||||
expectedErrs: field.ErrorList{
|
||||
field.Invalid(field.NewPath("spec", "sharedCounters").Index(0).Child("counters"), "InvalidKey", "").WithOrigin("format=k8s-short-name"),
|
||||
},
|
||||
},
|
||||
// spec.devices.consumesCounters.counters
|
||||
"invalid update: device counter key with uppercase": {
|
||||
old: mkResourceSlice(),
|
||||
update: mkResourceSlice(tweakSharedCounter("InvalidKey"), tweakDeviceCounter("InvalidKey")),
|
||||
expectedErrs: field.ErrorList{
|
||||
field.Invalid(field.NewPath("spec", "sharedCounters").Index(0).Child("counters"), "InvalidKey", "").WithOrigin("format=k8s-short-name"),
|
||||
field.Invalid(field.NewPath("spec", "devices").Index(0).Child("consumesCounters").Index(0).Child("counters"), "InvalidKey", "").WithOrigin("format=k8s-short-name"),
|
||||
},
|
||||
},
|
||||
}
|
||||
for k, tc := range testCases {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
|
|
@ -294,3 +332,29 @@ func tweakDeviceAttribute(name resource.QualifiedName, value resource.DeviceAttr
|
|||
rs.Spec.Devices[0].Attributes[name] = value
|
||||
}
|
||||
}
|
||||
|
||||
func tweakSharedCounter(key string) func(*resource.ResourceSlice) {
|
||||
return func(rs *resource.ResourceSlice) {
|
||||
rs.Spec.SharedCounters = []resource.CounterSet{
|
||||
{
|
||||
Name: "shared-counter-set",
|
||||
Counters: map[string]resource.Counter{
|
||||
key: {},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func tweakDeviceCounter(key string) func(*resource.ResourceSlice) {
|
||||
return func(rs *resource.ResourceSlice) {
|
||||
rs.Spec.Devices[0].ConsumesCounters = []resource.DeviceCounterConsumption{
|
||||
{
|
||||
CounterSet: "shared-counter-set",
|
||||
Counters: map[string]resource.Counter{
|
||||
key: {},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -315,6 +315,8 @@ message CounterSet {
|
|||
// The maximum number of counters in all sets is 32.
|
||||
//
|
||||
// +required
|
||||
// +k8s:required
|
||||
// +k8s:eachKey=+k8s:format=k8s-short-name
|
||||
map<string, Counter> counters = 2;
|
||||
}
|
||||
|
||||
|
|
@ -779,6 +781,8 @@ message DeviceCounterConsumption {
|
|||
// 16 counters each).
|
||||
//
|
||||
// +required
|
||||
// +k8s:required
|
||||
// +k8s:eachKey=+k8s:format=k8s-short-name
|
||||
map<string, Counter> counters = 2;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -202,6 +202,8 @@ type CounterSet struct {
|
|||
// The maximum number of counters in all sets is 32.
|
||||
//
|
||||
// +required
|
||||
// +k8s:required
|
||||
// +k8s:eachKey=+k8s:format=k8s-short-name
|
||||
Counters map[string]Counter `json:"counters,omitempty" protobuf:"bytes,2,name=counters"`
|
||||
}
|
||||
|
||||
|
|
@ -417,6 +419,8 @@ type DeviceCounterConsumption struct {
|
|||
// 16 counters each).
|
||||
//
|
||||
// +required
|
||||
// +k8s:required
|
||||
// +k8s:eachKey=+k8s:format=k8s-short-name
|
||||
Counters map[string]Counter `json:"counters,omitempty" protobuf:"bytes,2,opt,name=counters"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -451,6 +451,8 @@ message CounterSet {
|
|||
// The maximum number of counters is 32.
|
||||
//
|
||||
// +required
|
||||
// +k8s:required
|
||||
// +k8s:eachKey=+k8s:format=k8s-short-name
|
||||
map<string, Counter> counters = 2;
|
||||
}
|
||||
|
||||
|
|
@ -787,6 +789,8 @@ message DeviceCounterConsumption {
|
|||
// 16 counters each).
|
||||
//
|
||||
// +required
|
||||
// +k8s:required
|
||||
// +k8s:eachKey=+k8s:format=k8s-short-name
|
||||
map<string, Counter> counters = 2;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -202,6 +202,8 @@ type CounterSet struct {
|
|||
// The maximum number of counters is 32.
|
||||
//
|
||||
// +required
|
||||
// +k8s:required
|
||||
// +k8s:eachKey=+k8s:format=k8s-short-name
|
||||
Counters map[string]Counter `json:"counters,omitempty" protobuf:"bytes,2,name=counters"`
|
||||
}
|
||||
|
||||
|
|
@ -429,6 +431,8 @@ type DeviceCounterConsumption struct {
|
|||
// 16 counters each).
|
||||
//
|
||||
// +required
|
||||
// +k8s:required
|
||||
// +k8s:eachKey=+k8s:format=k8s-short-name
|
||||
Counters map[string]Counter `json:"counters,omitempty" protobuf:"bytes,2,opt,name=counters"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -315,6 +315,8 @@ message CounterSet {
|
|||
// The maximum number of counters in all sets is 32.
|
||||
//
|
||||
// +required
|
||||
// +k8s:required
|
||||
// +k8s:eachKey=+k8s:format=k8s-short-name
|
||||
map<string, Counter> counters = 2;
|
||||
}
|
||||
|
||||
|
|
@ -779,6 +781,8 @@ message DeviceCounterConsumption {
|
|||
// 16 counters each).
|
||||
//
|
||||
// +required
|
||||
// +k8s:required
|
||||
// +k8s:eachKey=+k8s:format=k8s-short-name
|
||||
map<string, Counter> counters = 2;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -202,6 +202,8 @@ type CounterSet struct {
|
|||
// The maximum number of counters in all sets is 32.
|
||||
//
|
||||
// +required
|
||||
// +k8s:required
|
||||
// +k8s:eachKey=+k8s:format=k8s-short-name
|
||||
Counters map[string]Counter `json:"counters,omitempty" protobuf:"bytes,2,name=counters"`
|
||||
}
|
||||
|
||||
|
|
@ -417,6 +419,8 @@ type DeviceCounterConsumption struct {
|
|||
// 16 counters each).
|
||||
//
|
||||
// +required
|
||||
// +k8s:required
|
||||
// +k8s:eachKey=+k8s:format=k8s-short-name
|
||||
Counters map[string]Counter `json:"counters,omitempty" protobuf:"bytes,2,opt,name=counters"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ func (ektv eachKeyTagValidator) GetValidations(context Context, tag codetags.Tag
|
|||
|
||||
elemContext := Context{
|
||||
Scope: ScopeMapKey,
|
||||
Type: nt.Elem,
|
||||
Type: nt.Key,
|
||||
Path: context.Path.Key("(keys)"),
|
||||
Member: nil, // NA for map keys
|
||||
ParentPath: context.Path,
|
||||
|
|
|
|||
Loading…
Reference in a new issue