mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 14:07:14 +00:00
Merge pull request #15574 from derekwaynecarr/resource_quota_fractional
Auto commit by PR queue bot
This commit is contained in:
commit
f5afa634ff
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user