mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 02:09:56 +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)
|
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(
|
var standardQuotaResources = sets.NewString(
|
||||||
string(ResourceCPU),
|
string(ResourceCPU),
|
||||||
string(ResourceMemory),
|
string(ResourceMemory),
|
||||||
|
@ -2034,6 +2034,33 @@ func validateResourceQuotaResourceName(value string, fldPath *field.Path) field.
|
|||||||
return field.ErrorList{}
|
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.
|
// ValidateLimitRange tests if required fields in the LimitRange are set.
|
||||||
func ValidateLimitRange(limitRange *api.LimitRange) field.ErrorList {
|
func ValidateLimitRange(limitRange *api.LimitRange) field.ErrorList {
|
||||||
allErrs := ValidateObjectMeta(&limitRange.ObjectMeta, true, ValidateLimitRangeName, field.NewPath("metadata"))
|
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 {
|
for i := range limitRange.Spec.Limits {
|
||||||
idxPath := fldPath.Index(i)
|
idxPath := fldPath.Index(i)
|
||||||
limit := &limitRange.Spec.Limits[i]
|
limit := &limitRange.Spec.Limits[i]
|
||||||
|
allErrs = append(allErrs, validateLimitRangeTypeName(string(limit.Type), idxPath.Child("type"))...)
|
||||||
|
|
||||||
_, found := limitTypeSet[limit.Type]
|
_, found := limitTypeSet[limit.Type]
|
||||||
if found {
|
if found {
|
||||||
allErrs = append(allErrs, field.Duplicate(idxPath.Child("type"), limit.Type))
|
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{}
|
maxLimitRequestRatios := map[string]resource.Quantity{}
|
||||||
|
|
||||||
for k, q := range limit.Max {
|
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))
|
keys.Insert(string(k))
|
||||||
max[string(k)] = q
|
max[string(k)] = q
|
||||||
}
|
}
|
||||||
for k, q := range limit.Min {
|
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))
|
keys.Insert(string(k))
|
||||||
min[string(k)] = q
|
min[string(k)] = q
|
||||||
}
|
}
|
||||||
@ -2077,19 +2106,19 @@ func ValidateLimitRange(limitRange *api.LimitRange) field.ErrorList {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for k, q := range limit.Default {
|
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))
|
keys.Insert(string(k))
|
||||||
defaults[string(k)] = q
|
defaults[string(k)] = q
|
||||||
}
|
}
|
||||||
for k, q := range limit.DefaultRequest {
|
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))
|
keys.Insert(string(k))
|
||||||
defaultRequests[string(k)] = q
|
defaultRequests[string(k)] = q
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, q := range limit.MaxLimitRequestRatio {
|
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))
|
keys.Insert(string(k))
|
||||||
maxLimitRequestRatios[string(k)] = q
|
maxLimitRequestRatios[string(k)] = q
|
||||||
}
|
}
|
||||||
|
@ -3864,6 +3864,14 @@ func getResourceList(cpu, memory string) api.ResourceList {
|
|||||||
return res
|
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) {
|
func TestValidateLimitRange(t *testing.T) {
|
||||||
successCases := []struct {
|
successCases := []struct {
|
||||||
name string
|
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 {
|
for _, successCase := range successCases {
|
||||||
@ -4052,6 +4090,21 @@ func TestValidateLimitRange(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
"ratio 10 is greater than max/min = 4.000000",
|
"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 {
|
for k, v := range errorCases {
|
||||||
|
Loading…
Reference in New Issue
Block a user