mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 22:46:12 +00:00
Merge pull request #22766 from aveshagarwal/master-limitranges-validation-fix
Auto commit by PR queue bot
This commit is contained in:
commit
7341b0a265
@ -127,6 +127,16 @@ func IsStandardContainerResourceName(str string) bool {
|
||||
return standardContainerResources.Has(str)
|
||||
}
|
||||
|
||||
var standardLimitRangeTypes = sets.NewString(
|
||||
string(LimitTypePod),
|
||||
string(LimitTypeContainer),
|
||||
)
|
||||
|
||||
// IsStandardLimitRangeType returns true if the type is Pod or Container
|
||||
func IsStandardLimitRangeType(str string) bool {
|
||||
return standardLimitRangeTypes.Has(str)
|
||||
}
|
||||
|
||||
var standardQuotaResources = sets.NewString(
|
||||
string(ResourceCPU),
|
||||
string(ResourceMemory),
|
||||
|
@ -2034,6 +2034,33 @@ func validateResourceQuotaResourceName(value string, fldPath *field.Path) field.
|
||||
return field.ErrorList{}
|
||||
}
|
||||
|
||||
// Validate limit range types
|
||||
func validateLimitRangeTypeName(value string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if !validation.IsQualifiedName(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, qualifiedNameErrorMsg))
|
||||
}
|
||||
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !api.IsStandardLimitRangeType(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard limit type or fully qualified"))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// Validate limit range resource name
|
||||
// limit types (other than Pod/Container) could contain storage not just cpu or memory
|
||||
func validateLimitRangeResourceName(limitType api.LimitType, value string, fldPath *field.Path) field.ErrorList {
|
||||
switch limitType {
|
||||
case api.LimitTypePod, api.LimitTypeContainer:
|
||||
return validateContainerResourceName(value, fldPath)
|
||||
default:
|
||||
return validateResourceName(value, fldPath)
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateLimitRange tests if required fields in the LimitRange are set.
|
||||
func ValidateLimitRange(limitRange *api.LimitRange) field.ErrorList {
|
||||
allErrs := ValidateObjectMeta(&limitRange.ObjectMeta, true, ValidateLimitRangeName, field.NewPath("metadata"))
|
||||
@ -2044,6 +2071,8 @@ func ValidateLimitRange(limitRange *api.LimitRange) field.ErrorList {
|
||||
for i := range limitRange.Spec.Limits {
|
||||
idxPath := fldPath.Index(i)
|
||||
limit := &limitRange.Spec.Limits[i]
|
||||
allErrs = append(allErrs, validateLimitRangeTypeName(string(limit.Type), idxPath.Child("type"))...)
|
||||
|
||||
_, found := limitTypeSet[limit.Type]
|
||||
if found {
|
||||
allErrs = append(allErrs, field.Duplicate(idxPath.Child("type"), limit.Type))
|
||||
@ -2058,12 +2087,12 @@ func ValidateLimitRange(limitRange *api.LimitRange) field.ErrorList {
|
||||
maxLimitRequestRatios := map[string]resource.Quantity{}
|
||||
|
||||
for k, q := range limit.Max {
|
||||
allErrs = append(allErrs, validateContainerResourceName(string(k), idxPath.Child("max").Key(string(k)))...)
|
||||
allErrs = append(allErrs, validateLimitRangeResourceName(limit.Type, string(k), idxPath.Child("max").Key(string(k)))...)
|
||||
keys.Insert(string(k))
|
||||
max[string(k)] = q
|
||||
}
|
||||
for k, q := range limit.Min {
|
||||
allErrs = append(allErrs, validateContainerResourceName(string(k), idxPath.Child("min").Key(string(k)))...)
|
||||
allErrs = append(allErrs, validateLimitRangeResourceName(limit.Type, string(k), idxPath.Child("min").Key(string(k)))...)
|
||||
keys.Insert(string(k))
|
||||
min[string(k)] = q
|
||||
}
|
||||
@ -2077,19 +2106,19 @@ func ValidateLimitRange(limitRange *api.LimitRange) field.ErrorList {
|
||||
}
|
||||
} else {
|
||||
for k, q := range limit.Default {
|
||||
allErrs = append(allErrs, validateContainerResourceName(string(k), idxPath.Child("default").Key(string(k)))...)
|
||||
allErrs = append(allErrs, validateLimitRangeResourceName(limit.Type, string(k), idxPath.Child("default").Key(string(k)))...)
|
||||
keys.Insert(string(k))
|
||||
defaults[string(k)] = q
|
||||
}
|
||||
for k, q := range limit.DefaultRequest {
|
||||
allErrs = append(allErrs, validateContainerResourceName(string(k), idxPath.Child("defaultRequest").Key(string(k)))...)
|
||||
allErrs = append(allErrs, validateLimitRangeResourceName(limit.Type, string(k), idxPath.Child("defaultRequest").Key(string(k)))...)
|
||||
keys.Insert(string(k))
|
||||
defaultRequests[string(k)] = q
|
||||
}
|
||||
}
|
||||
|
||||
for k, q := range limit.MaxLimitRequestRatio {
|
||||
allErrs = append(allErrs, validateContainerResourceName(string(k), idxPath.Child("maxLimitRequestRatio").Key(string(k)))...)
|
||||
allErrs = append(allErrs, validateLimitRangeResourceName(limit.Type, string(k), idxPath.Child("maxLimitRequestRatio").Key(string(k)))...)
|
||||
keys.Insert(string(k))
|
||||
maxLimitRequestRatios[string(k)] = q
|
||||
}
|
||||
|
@ -3864,6 +3864,14 @@ func getResourceList(cpu, memory string) api.ResourceList {
|
||||
return res
|
||||
}
|
||||
|
||||
func getStorageResourceList(storage string) api.ResourceList {
|
||||
res := api.ResourceList{}
|
||||
if storage != "" {
|
||||
res[api.ResourceStorage] = resource.MustParse(storage)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func TestValidateLimitRange(t *testing.T) {
|
||||
successCases := []struct {
|
||||
name string
|
||||
@ -3905,6 +3913,36 @@ func TestValidateLimitRange(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "thirdparty-fields-all-valid-standard-container-resources",
|
||||
spec: api.LimitRangeSpec{
|
||||
Limits: []api.LimitRangeItem{
|
||||
{
|
||||
Type: "thirdparty.com/foo",
|
||||
Max: getResourceList("100m", "10000T"),
|
||||
Min: getResourceList("5m", "100Mi"),
|
||||
Default: getResourceList("50m", "500Mi"),
|
||||
DefaultRequest: getResourceList("10m", "200Mi"),
|
||||
MaxLimitRequestRatio: getResourceList("10", ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "thirdparty-fields-all-valid-storage-resources",
|
||||
spec: api.LimitRangeSpec{
|
||||
Limits: []api.LimitRangeItem{
|
||||
{
|
||||
Type: "thirdparty.com/foo",
|
||||
Max: getStorageResourceList("10000T"),
|
||||
Min: getStorageResourceList("100Mi"),
|
||||
Default: getStorageResourceList("500Mi"),
|
||||
DefaultRequest: getStorageResourceList("200Mi"),
|
||||
MaxLimitRequestRatio: getStorageResourceList(""),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, successCase := range successCases {
|
||||
@ -4052,6 +4090,21 @@ func TestValidateLimitRange(t *testing.T) {
|
||||
}},
|
||||
"ratio 10 is greater than max/min = 4.000000",
|
||||
},
|
||||
"invalid non standard limit type": {
|
||||
api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: api.LimitRangeSpec{
|
||||
Limits: []api.LimitRangeItem{
|
||||
{
|
||||
Type: "foo",
|
||||
Max: getStorageResourceList("10000T"),
|
||||
Min: getStorageResourceList("100Mi"),
|
||||
Default: getStorageResourceList("500Mi"),
|
||||
DefaultRequest: getStorageResourceList("200Mi"),
|
||||
MaxLimitRequestRatio: getStorageResourceList(""),
|
||||
},
|
||||
},
|
||||
}},
|
||||
"must be a standard limit type or fully qualified",
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range errorCases {
|
||||
|
Loading…
Reference in New Issue
Block a user