mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Fix validation of resources (cpu, memory, storage) for limit range types.
This commit is contained in:
		@@ -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 {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user