mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #15574 from derekwaynecarr/resource_quota_fractional
Auto commit by PR queue bot
This commit is contained in:
		@@ -80,20 +80,36 @@ var Semantic = conversion.EqualitiesOrDie(
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var standardResources = sets.NewString(
 | 
					var standardResources = sets.NewString(
 | 
				
			||||||
	string(ResourceMemory),
 | 
					 | 
				
			||||||
	string(ResourceCPU),
 | 
						string(ResourceCPU),
 | 
				
			||||||
 | 
						string(ResourceMemory),
 | 
				
			||||||
	string(ResourcePods),
 | 
						string(ResourcePods),
 | 
				
			||||||
	string(ResourceQuotas),
 | 
						string(ResourceQuotas),
 | 
				
			||||||
	string(ResourceServices),
 | 
						string(ResourceServices),
 | 
				
			||||||
	string(ResourceReplicationControllers),
 | 
						string(ResourceReplicationControllers),
 | 
				
			||||||
	string(ResourceSecrets),
 | 
						string(ResourceSecrets),
 | 
				
			||||||
	string(ResourcePersistentVolumeClaims),
 | 
						string(ResourcePersistentVolumeClaims),
 | 
				
			||||||
	string(ResourceStorage))
 | 
						string(ResourceStorage),
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsStandardResourceName returns true if the resource is known to the system
 | 
				
			||||||
func IsStandardResourceName(str string) bool {
 | 
					func IsStandardResourceName(str string) bool {
 | 
				
			||||||
	return standardResources.Has(str)
 | 
						return standardResources.Has(str)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var integerResources = sets.NewString(
 | 
				
			||||||
 | 
						string(ResourcePods),
 | 
				
			||||||
 | 
						string(ResourceQuotas),
 | 
				
			||||||
 | 
						string(ResourceServices),
 | 
				
			||||||
 | 
						string(ResourceReplicationControllers),
 | 
				
			||||||
 | 
						string(ResourceSecrets),
 | 
				
			||||||
 | 
						string(ResourcePersistentVolumeClaims),
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsIntegerResourceName returns true if the resource is measured in integer values
 | 
				
			||||||
 | 
					func IsIntegerResourceName(str string) bool {
 | 
				
			||||||
 | 
						return integerResources.Has(str)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewDeleteOptions returns a DeleteOptions indicating the resource should
 | 
					// NewDeleteOptions returns a DeleteOptions indicating the resource should
 | 
				
			||||||
// be deleted within the specified grace period. Use zero to indicate
 | 
					// be deleted within the specified grace period. Use zero to indicate
 | 
				
			||||||
// immediate deletion. If you would prefer to use the default grace period,
 | 
					// immediate deletion. If you would prefer to use the default grace period,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,6 +44,7 @@ var RepairMalformedUpdates bool = true
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const cIdentifierErrorMsg string = `must be a C identifier (matching regex ` + validation.CIdentifierFmt + `): e.g. "my_name" or "MyName"`
 | 
					const cIdentifierErrorMsg string = `must be a C identifier (matching regex ` + validation.CIdentifierFmt + `): e.g. "my_name" or "MyName"`
 | 
				
			||||||
const isNegativeErrorMsg string = `must be non-negative`
 | 
					const isNegativeErrorMsg string = `must be non-negative`
 | 
				
			||||||
 | 
					const isNotIntegerErrorMsg string = `must be an integer`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func intervalErrorMsg(lo, hi int) string {
 | 
					func intervalErrorMsg(lo, hi int) string {
 | 
				
			||||||
	return fmt.Sprintf(`must be greater than %d and less than %d`, lo, hi)
 | 
						return fmt.Sprintf(`must be greater than %d and less than %d`, lo, hi)
 | 
				
			||||||
@@ -1765,15 +1766,27 @@ func ValidateResourceQuota(resourceQuota *api.ResourceQuota) errs.ValidationErro
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for k, v := range resourceQuota.Spec.Hard {
 | 
						for k, v := range resourceQuota.Spec.Hard {
 | 
				
			||||||
		allErrs = append(allErrs, validateResourceName(string(k), string(resourceQuota.TypeMeta.Kind))...)
 | 
							allErrs = append(allErrs, validateResourceName(string(k), string(resourceQuota.TypeMeta.Kind))...)
 | 
				
			||||||
		allErrs = append(allErrs, ValidatePositiveQuantity(v, string(k))...)
 | 
							allErrs = append(allErrs, validateResourceQuantityValue(string(k), v)...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for k, v := range resourceQuota.Status.Hard {
 | 
						for k, v := range resourceQuota.Status.Hard {
 | 
				
			||||||
		allErrs = append(allErrs, validateResourceName(string(k), string(resourceQuota.TypeMeta.Kind))...)
 | 
							allErrs = append(allErrs, validateResourceName(string(k), string(resourceQuota.TypeMeta.Kind))...)
 | 
				
			||||||
		allErrs = append(allErrs, ValidatePositiveQuantity(v, string(k))...)
 | 
							allErrs = append(allErrs, validateResourceQuantityValue(string(k), v)...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for k, v := range resourceQuota.Status.Used {
 | 
						for k, v := range resourceQuota.Status.Used {
 | 
				
			||||||
		allErrs = append(allErrs, validateResourceName(string(k), string(resourceQuota.TypeMeta.Kind))...)
 | 
							allErrs = append(allErrs, validateResourceName(string(k), string(resourceQuota.TypeMeta.Kind))...)
 | 
				
			||||||
		allErrs = append(allErrs, ValidatePositiveQuantity(v, string(k))...)
 | 
							allErrs = append(allErrs, validateResourceQuantityValue(string(k), v)...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// validateResourceQuantityValue enforces that specified quantity is valid for specified resource
 | 
				
			||||||
 | 
					func validateResourceQuantityValue(resource string, value resource.Quantity) errs.ValidationErrorList {
 | 
				
			||||||
 | 
						allErrs := errs.ValidationErrorList{}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidatePositiveQuantity(value, resource)...)
 | 
				
			||||||
 | 
						if api.IsIntegerResourceName(resource) {
 | 
				
			||||||
 | 
							if value.MilliValue()%int64(1000) != int64(0) {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, errs.NewFieldInvalid(resource, value, isNotIntegerErrorMsg))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return allErrs
 | 
						return allErrs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1783,8 +1796,9 @@ func ValidateResourceQuota(resourceQuota *api.ResourceQuota) errs.ValidationErro
 | 
				
			|||||||
func ValidateResourceQuotaUpdate(newResourceQuota, oldResourceQuota *api.ResourceQuota) errs.ValidationErrorList {
 | 
					func ValidateResourceQuotaUpdate(newResourceQuota, oldResourceQuota *api.ResourceQuota) errs.ValidationErrorList {
 | 
				
			||||||
	allErrs := errs.ValidationErrorList{}
 | 
						allErrs := errs.ValidationErrorList{}
 | 
				
			||||||
	allErrs = append(allErrs, ValidateObjectMetaUpdate(&newResourceQuota.ObjectMeta, &oldResourceQuota.ObjectMeta).Prefix("metadata")...)
 | 
						allErrs = append(allErrs, ValidateObjectMetaUpdate(&newResourceQuota.ObjectMeta, &oldResourceQuota.ObjectMeta).Prefix("metadata")...)
 | 
				
			||||||
	for k := range newResourceQuota.Spec.Hard {
 | 
						for k, v := range newResourceQuota.Spec.Hard {
 | 
				
			||||||
		allErrs = append(allErrs, validateResourceName(string(k), string(newResourceQuota.TypeMeta.Kind))...)
 | 
							allErrs = append(allErrs, validateResourceName(string(k), string(newResourceQuota.TypeMeta.Kind))...)
 | 
				
			||||||
 | 
							allErrs = append(allErrs, validateResourceQuantityValue(string(k), v)...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	newResourceQuota.Status = oldResourceQuota.Status
 | 
						newResourceQuota.Status = oldResourceQuota.Status
 | 
				
			||||||
	return allErrs
 | 
						return allErrs
 | 
				
			||||||
@@ -1798,11 +1812,13 @@ func ValidateResourceQuotaStatusUpdate(newResourceQuota, oldResourceQuota *api.R
 | 
				
			|||||||
	if newResourceQuota.ResourceVersion == "" {
 | 
						if newResourceQuota.ResourceVersion == "" {
 | 
				
			||||||
		allErrs = append(allErrs, errs.NewFieldRequired("resourceVersion"))
 | 
							allErrs = append(allErrs, errs.NewFieldRequired("resourceVersion"))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for k := range newResourceQuota.Status.Hard {
 | 
						for k, v := range newResourceQuota.Status.Hard {
 | 
				
			||||||
		allErrs = append(allErrs, validateResourceName(string(k), string(newResourceQuota.TypeMeta.Kind))...)
 | 
							allErrs = append(allErrs, validateResourceName(string(k), string(newResourceQuota.TypeMeta.Kind))...)
 | 
				
			||||||
 | 
							allErrs = append(allErrs, validateResourceQuantityValue(string(k), v)...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for k := range newResourceQuota.Status.Used {
 | 
						for k, v := range newResourceQuota.Status.Used {
 | 
				
			||||||
		allErrs = append(allErrs, validateResourceName(string(k), string(newResourceQuota.TypeMeta.Kind))...)
 | 
							allErrs = append(allErrs, validateResourceName(string(k), string(newResourceQuota.TypeMeta.Kind))...)
 | 
				
			||||||
 | 
							allErrs = append(allErrs, validateResourceQuantityValue(string(k), v)...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	newResourceQuota.Spec = oldResourceQuota.Spec
 | 
						newResourceQuota.Spec = oldResourceQuota.Spec
 | 
				
			||||||
	return allErrs
 | 
						return allErrs
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3244,6 +3244,21 @@ func TestValidateResourceQuota(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fractionalComputeSpec := api.ResourceQuotaSpec{
 | 
				
			||||||
 | 
							Hard: api.ResourceList{
 | 
				
			||||||
 | 
								api.ResourceCPU: resource.MustParse("100m"),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fractionalPodSpec := api.ResourceQuotaSpec{
 | 
				
			||||||
 | 
							Hard: api.ResourceList{
 | 
				
			||||||
 | 
								api.ResourcePods:                   resource.MustParse(".1"),
 | 
				
			||||||
 | 
								api.ResourceServices:               resource.MustParse(".5"),
 | 
				
			||||||
 | 
								api.ResourceReplicationControllers: resource.MustParse("1.25"),
 | 
				
			||||||
 | 
								api.ResourceQuotas:                 resource.MustParse("2.5"),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	successCases := []api.ResourceQuota{
 | 
						successCases := []api.ResourceQuota{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			ObjectMeta: api.ObjectMeta{
 | 
								ObjectMeta: api.ObjectMeta{
 | 
				
			||||||
@@ -3252,6 +3267,13 @@ func TestValidateResourceQuota(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			Spec: spec,
 | 
								Spec: spec,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ObjectMeta: api.ObjectMeta{
 | 
				
			||||||
 | 
									Name:      "abc",
 | 
				
			||||||
 | 
									Namespace: "foo",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								Spec: fractionalComputeSpec,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, successCase := range successCases {
 | 
						for _, successCase := range successCases {
 | 
				
			||||||
@@ -3284,6 +3306,10 @@ func TestValidateResourceQuota(t *testing.T) {
 | 
				
			|||||||
			api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: negativeSpec},
 | 
								api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: negativeSpec},
 | 
				
			||||||
			isNegativeErrorMsg,
 | 
								isNegativeErrorMsg,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							"fractional-api-resource": {
 | 
				
			||||||
 | 
								api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: fractionalPodSpec},
 | 
				
			||||||
 | 
								isNotIntegerErrorMsg,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for k, v := range errorCases {
 | 
						for k, v := range errorCases {
 | 
				
			||||||
		errs := ValidateResourceQuota(&v.R)
 | 
							errs := ValidateResourceQuota(&v.R)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user