Merge pull request #22766 from aveshagarwal/master-limitranges-validation-fix

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2016-03-10 15:59:23 -08:00
commit 7341b0a265
3 changed files with 97 additions and 5 deletions

View File

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

View File

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

View File

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