mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #22766 from aveshagarwal/master-limitranges-validation-fix
Auto commit by PR queue bot
This commit is contained in:
		@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user