mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 10:19:50 +00:00
generic set
This commit is contained in:
parent
92c4b3254f
commit
070e7a38cb
@ -390,19 +390,19 @@ func TestValidateStatefulSet(t *testing.T) {
|
|||||||
name: "invalid restart policy 1",
|
name: "invalid restart policy 1",
|
||||||
set: mkStatefulSet(&validPodTemplate, tweakTemplateRestartPolicy(api.RestartPolicyOnFailure)),
|
set: mkStatefulSet(&validPodTemplate, tweakTemplateRestartPolicy(api.RestartPolicyOnFailure)),
|
||||||
errs: field.ErrorList{
|
errs: field.ErrorList{
|
||||||
field.NotSupported(field.NewPath("spec", "template", "spec", "restartPolicy"), nil, nil),
|
field.NotSupported[string](field.NewPath("spec", "template", "spec", "restartPolicy"), nil, nil),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "invalid restart policy 2",
|
name: "invalid restart policy 2",
|
||||||
set: mkStatefulSet(&validPodTemplate, tweakTemplateRestartPolicy(api.RestartPolicyNever)),
|
set: mkStatefulSet(&validPodTemplate, tweakTemplateRestartPolicy(api.RestartPolicyNever)),
|
||||||
errs: field.ErrorList{
|
errs: field.ErrorList{
|
||||||
field.NotSupported(field.NewPath("spec", "template", "spec", "restartPolicy"), nil, nil),
|
field.NotSupported[string](field.NewPath("spec", "template", "spec", "restartPolicy"), nil, nil),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "empty restart policy",
|
name: "empty restart policy",
|
||||||
set: mkStatefulSet(&validPodTemplate, tweakTemplateRestartPolicy("")),
|
set: mkStatefulSet(&validPodTemplate, tweakTemplateRestartPolicy("")),
|
||||||
errs: field.ErrorList{
|
errs: field.ErrorList{
|
||||||
field.NotSupported(field.NewPath("spec", "template", "spec", "restartPolicy"), nil, nil),
|
field.NotSupported[string](field.NewPath("spec", "template", "spec", "restartPolicy"), nil, nil),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "invalid update strategy",
|
name: "invalid update strategy",
|
||||||
@ -468,8 +468,8 @@ func TestValidateStatefulSet(t *testing.T) {
|
|||||||
tweakPVCPolicy(mkPVCPolicy()),
|
tweakPVCPolicy(mkPVCPolicy()),
|
||||||
),
|
),
|
||||||
errs: field.ErrorList{
|
errs: field.ErrorList{
|
||||||
field.NotSupported(field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenDeleted"), nil, nil),
|
field.NotSupported[string](field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenDeleted"), nil, nil),
|
||||||
field.NotSupported(field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenScaled"), nil, nil),
|
field.NotSupported[string](field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenScaled"), nil, nil),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "invalid PersistentVolumeClaimRetentionPolicy " + enableStatefulSetAutoDeletePVC,
|
name: "invalid PersistentVolumeClaimRetentionPolicy " + enableStatefulSetAutoDeletePVC,
|
||||||
@ -480,8 +480,8 @@ func TestValidateStatefulSet(t *testing.T) {
|
|||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
errs: field.ErrorList{
|
errs: field.ErrorList{
|
||||||
field.NotSupported(field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenDeleted"), nil, nil),
|
field.NotSupported[string](field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenDeleted"), nil, nil),
|
||||||
field.NotSupported(field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenScaled"), nil, nil),
|
field.NotSupported[string](field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenScaled"), nil, nil),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "zero maxUnavailable",
|
name: "zero maxUnavailable",
|
||||||
|
@ -18,6 +18,7 @@ package validation
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
|
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
|
||||||
pathvalidation "k8s.io/apimachinery/pkg/api/validation/path"
|
pathvalidation "k8s.io/apimachinery/pkg/api/validation/path"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
@ -387,7 +388,7 @@ func validateContainerResourceSource(src *autoscaling.ContainerResourceMetricSou
|
|||||||
if len(src.Name) == 0 {
|
if len(src.Name) == 0 {
|
||||||
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "must specify a resource name"))
|
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "must specify a resource name"))
|
||||||
} else {
|
} else {
|
||||||
allErrs = append(allErrs, corevalidation.ValidateContainerResourceName(string(src.Name), fldPath.Child("name"))...)
|
allErrs = append(allErrs, corevalidation.ValidateContainerResourceName(src.Name, fldPath.Child("name"))...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(src.Container) == 0 {
|
if len(src.Container) == 0 {
|
||||||
|
@ -919,7 +919,7 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
msg: "Invalid value: \"InvalidResource\": must be a standard resource type or fully qualified",
|
msg: "Invalid value: InvalidResource: must be a standard resource type or fully qualified",
|
||||||
}, {
|
}, {
|
||||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||||
|
@ -113,34 +113,34 @@ var Semantic = conversion.EqualitiesOrDie(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
var standardResourceQuotaScopes = sets.NewString(
|
var standardResourceQuotaScopes = sets.New(
|
||||||
string(core.ResourceQuotaScopeTerminating),
|
core.ResourceQuotaScopeTerminating,
|
||||||
string(core.ResourceQuotaScopeNotTerminating),
|
core.ResourceQuotaScopeNotTerminating,
|
||||||
string(core.ResourceQuotaScopeBestEffort),
|
core.ResourceQuotaScopeBestEffort,
|
||||||
string(core.ResourceQuotaScopeNotBestEffort),
|
core.ResourceQuotaScopeNotBestEffort,
|
||||||
string(core.ResourceQuotaScopePriorityClass),
|
core.ResourceQuotaScopePriorityClass,
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsStandardResourceQuotaScope returns true if the scope is a standard value
|
// IsStandardResourceQuotaScope returns true if the scope is a standard value
|
||||||
func IsStandardResourceQuotaScope(str string) bool {
|
func IsStandardResourceQuotaScope(scope core.ResourceQuotaScope) bool {
|
||||||
return standardResourceQuotaScopes.Has(str) || str == string(core.ResourceQuotaScopeCrossNamespacePodAffinity)
|
return standardResourceQuotaScopes.Has(scope) || scope == core.ResourceQuotaScopeCrossNamespacePodAffinity
|
||||||
}
|
}
|
||||||
|
|
||||||
var podObjectCountQuotaResources = sets.NewString(
|
var podObjectCountQuotaResources = sets.New(
|
||||||
string(core.ResourcePods),
|
core.ResourcePods,
|
||||||
)
|
)
|
||||||
|
|
||||||
var podComputeQuotaResources = sets.NewString(
|
var podComputeQuotaResources = sets.New(
|
||||||
string(core.ResourceCPU),
|
core.ResourceCPU,
|
||||||
string(core.ResourceMemory),
|
core.ResourceMemory,
|
||||||
string(core.ResourceLimitsCPU),
|
core.ResourceLimitsCPU,
|
||||||
string(core.ResourceLimitsMemory),
|
core.ResourceLimitsMemory,
|
||||||
string(core.ResourceRequestsCPU),
|
core.ResourceRequestsCPU,
|
||||||
string(core.ResourceRequestsMemory),
|
core.ResourceRequestsMemory,
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsResourceQuotaScopeValidForResource returns true if the resource applies to the specified scope
|
// IsResourceQuotaScopeValidForResource returns true if the resource applies to the specified scope
|
||||||
func IsResourceQuotaScopeValidForResource(scope core.ResourceQuotaScope, resource string) bool {
|
func IsResourceQuotaScopeValidForResource(scope core.ResourceQuotaScope, resource core.ResourceName) bool {
|
||||||
switch scope {
|
switch scope {
|
||||||
case core.ResourceQuotaScopeTerminating, core.ResourceQuotaScopeNotTerminating, core.ResourceQuotaScopeNotBestEffort,
|
case core.ResourceQuotaScopeTerminating, core.ResourceQuotaScopeNotTerminating, core.ResourceQuotaScopeNotBestEffort,
|
||||||
core.ResourceQuotaScopePriorityClass, core.ResourceQuotaScopeCrossNamespacePodAffinity:
|
core.ResourceQuotaScopePriorityClass, core.ResourceQuotaScopeCrossNamespacePodAffinity:
|
||||||
@ -152,16 +152,16 @@ func IsResourceQuotaScopeValidForResource(scope core.ResourceQuotaScope, resourc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var standardContainerResources = sets.NewString(
|
var standardContainerResources = sets.New(
|
||||||
string(core.ResourceCPU),
|
core.ResourceCPU,
|
||||||
string(core.ResourceMemory),
|
core.ResourceMemory,
|
||||||
string(core.ResourceEphemeralStorage),
|
core.ResourceEphemeralStorage,
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsStandardContainerResourceName returns true if the container can make a resource request
|
// IsStandardContainerResourceName returns true if the container can make a resource request
|
||||||
// for the specified resource
|
// for the specified resource
|
||||||
func IsStandardContainerResourceName(str string) bool {
|
func IsStandardContainerResourceName(name core.ResourceName) bool {
|
||||||
return standardContainerResources.Has(str) || IsHugePageResourceName(core.ResourceName(str))
|
return standardContainerResources.Has(name) || IsHugePageResourceName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsExtendedResourceName returns true if:
|
// IsExtendedResourceName returns true if:
|
||||||
@ -196,88 +196,88 @@ func IsOvercommitAllowed(name core.ResourceName) bool {
|
|||||||
!IsHugePageResourceName(name)
|
!IsHugePageResourceName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
var standardLimitRangeTypes = sets.NewString(
|
var standardLimitRangeTypes = sets.New(
|
||||||
string(core.LimitTypePod),
|
core.LimitTypePod,
|
||||||
string(core.LimitTypeContainer),
|
core.LimitTypeContainer,
|
||||||
string(core.LimitTypePersistentVolumeClaim),
|
core.LimitTypePersistentVolumeClaim,
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsStandardLimitRangeType returns true if the type is Pod or Container
|
// IsStandardLimitRangeType returns true if the type is Pod or Container
|
||||||
func IsStandardLimitRangeType(str string) bool {
|
func IsStandardLimitRangeType(value core.LimitType) bool {
|
||||||
return standardLimitRangeTypes.Has(str)
|
return standardLimitRangeTypes.Has(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
var standardQuotaResources = sets.NewString(
|
var standardQuotaResources = sets.New(
|
||||||
string(core.ResourceCPU),
|
core.ResourceCPU,
|
||||||
string(core.ResourceMemory),
|
core.ResourceMemory,
|
||||||
string(core.ResourceEphemeralStorage),
|
core.ResourceEphemeralStorage,
|
||||||
string(core.ResourceRequestsCPU),
|
core.ResourceRequestsCPU,
|
||||||
string(core.ResourceRequestsMemory),
|
core.ResourceRequestsMemory,
|
||||||
string(core.ResourceRequestsStorage),
|
core.ResourceRequestsStorage,
|
||||||
string(core.ResourceRequestsEphemeralStorage),
|
core.ResourceRequestsEphemeralStorage,
|
||||||
string(core.ResourceLimitsCPU),
|
core.ResourceLimitsCPU,
|
||||||
string(core.ResourceLimitsMemory),
|
core.ResourceLimitsMemory,
|
||||||
string(core.ResourceLimitsEphemeralStorage),
|
core.ResourceLimitsEphemeralStorage,
|
||||||
string(core.ResourcePods),
|
core.ResourcePods,
|
||||||
string(core.ResourceQuotas),
|
core.ResourceQuotas,
|
||||||
string(core.ResourceServices),
|
core.ResourceServices,
|
||||||
string(core.ResourceReplicationControllers),
|
core.ResourceReplicationControllers,
|
||||||
string(core.ResourceSecrets),
|
core.ResourceSecrets,
|
||||||
string(core.ResourcePersistentVolumeClaims),
|
core.ResourcePersistentVolumeClaims,
|
||||||
string(core.ResourceConfigMaps),
|
core.ResourceConfigMaps,
|
||||||
string(core.ResourceServicesNodePorts),
|
core.ResourceServicesNodePorts,
|
||||||
string(core.ResourceServicesLoadBalancers),
|
core.ResourceServicesLoadBalancers,
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsStandardQuotaResourceName returns true if the resource is known to
|
// IsStandardQuotaResourceName returns true if the resource is known to
|
||||||
// the quota tracking system
|
// the quota tracking system
|
||||||
func IsStandardQuotaResourceName(str string) bool {
|
func IsStandardQuotaResourceName(name core.ResourceName) bool {
|
||||||
return standardQuotaResources.Has(str) || IsQuotaHugePageResourceName(core.ResourceName(str))
|
return standardQuotaResources.Has(name) || IsQuotaHugePageResourceName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
var standardResources = sets.NewString(
|
var standardResources = sets.New(
|
||||||
string(core.ResourceCPU),
|
core.ResourceCPU,
|
||||||
string(core.ResourceMemory),
|
core.ResourceMemory,
|
||||||
string(core.ResourceEphemeralStorage),
|
core.ResourceEphemeralStorage,
|
||||||
string(core.ResourceRequestsCPU),
|
core.ResourceRequestsCPU,
|
||||||
string(core.ResourceRequestsMemory),
|
core.ResourceRequestsMemory,
|
||||||
string(core.ResourceRequestsEphemeralStorage),
|
core.ResourceRequestsEphemeralStorage,
|
||||||
string(core.ResourceLimitsCPU),
|
core.ResourceLimitsCPU,
|
||||||
string(core.ResourceLimitsMemory),
|
core.ResourceLimitsMemory,
|
||||||
string(core.ResourceLimitsEphemeralStorage),
|
core.ResourceLimitsEphemeralStorage,
|
||||||
string(core.ResourcePods),
|
core.ResourcePods,
|
||||||
string(core.ResourceQuotas),
|
core.ResourceQuotas,
|
||||||
string(core.ResourceServices),
|
core.ResourceServices,
|
||||||
string(core.ResourceReplicationControllers),
|
core.ResourceReplicationControllers,
|
||||||
string(core.ResourceSecrets),
|
core.ResourceSecrets,
|
||||||
string(core.ResourceConfigMaps),
|
core.ResourceConfigMaps,
|
||||||
string(core.ResourcePersistentVolumeClaims),
|
core.ResourcePersistentVolumeClaims,
|
||||||
string(core.ResourceStorage),
|
core.ResourceStorage,
|
||||||
string(core.ResourceRequestsStorage),
|
core.ResourceRequestsStorage,
|
||||||
string(core.ResourceServicesNodePorts),
|
core.ResourceServicesNodePorts,
|
||||||
string(core.ResourceServicesLoadBalancers),
|
core.ResourceServicesLoadBalancers,
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsStandardResourceName returns true if the resource is known to the system
|
// IsStandardResourceName returns true if the resource is known to the system
|
||||||
func IsStandardResourceName(str string) bool {
|
func IsStandardResourceName(name core.ResourceName) bool {
|
||||||
return standardResources.Has(str) || IsQuotaHugePageResourceName(core.ResourceName(str))
|
return standardResources.Has(name) || IsQuotaHugePageResourceName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
var integerResources = sets.NewString(
|
var integerResources = sets.New(
|
||||||
string(core.ResourcePods),
|
core.ResourcePods,
|
||||||
string(core.ResourceQuotas),
|
core.ResourceQuotas,
|
||||||
string(core.ResourceServices),
|
core.ResourceServices,
|
||||||
string(core.ResourceReplicationControllers),
|
core.ResourceReplicationControllers,
|
||||||
string(core.ResourceSecrets),
|
core.ResourceSecrets,
|
||||||
string(core.ResourceConfigMaps),
|
core.ResourceConfigMaps,
|
||||||
string(core.ResourcePersistentVolumeClaims),
|
core.ResourcePersistentVolumeClaims,
|
||||||
string(core.ResourceServicesNodePorts),
|
core.ResourceServicesNodePorts,
|
||||||
string(core.ResourceServicesLoadBalancers),
|
core.ResourceServicesLoadBalancers,
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsIntegerResourceName returns true if the resource is measured in integer values
|
// IsIntegerResourceName returns true if the resource is measured in integer values
|
||||||
func IsIntegerResourceName(str string) bool {
|
func IsIntegerResourceName(name core.ResourceName) bool {
|
||||||
return integerResources.Has(str) || IsExtendedResourceName(core.ResourceName(str))
|
return integerResources.Has(name) || IsExtendedResourceName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsServiceIPSet aims to check if the service's ClusterIP is set or not
|
// IsServiceIPSet aims to check if the service's ClusterIP is set or not
|
||||||
@ -289,7 +289,7 @@ func IsServiceIPSet(service *core.Service) bool {
|
|||||||
service.Spec.ClusterIP != core.ClusterIPNone
|
service.Spec.ClusterIP != core.ClusterIPNone
|
||||||
}
|
}
|
||||||
|
|
||||||
var standardFinalizers = sets.NewString(
|
var standardFinalizers = sets.New(
|
||||||
string(core.FinalizerKubernetes),
|
string(core.FinalizerKubernetes),
|
||||||
metav1.FinalizerOrphanDependents,
|
metav1.FinalizerOrphanDependents,
|
||||||
metav1.FinalizerDeleteDependents,
|
metav1.FinalizerDeleteDependents,
|
||||||
|
@ -60,7 +60,7 @@ func TestIsStandardResource(t *testing.T) {
|
|||||||
{"requests.hugepages-2Mi", true},
|
{"requests.hugepages-2Mi", true},
|
||||||
}
|
}
|
||||||
for i, tc := range testCases {
|
for i, tc := range testCases {
|
||||||
if IsStandardResourceName(tc.input) != tc.output {
|
if IsStandardResourceName(core.ResourceName(tc.input)) != tc.output {
|
||||||
t.Errorf("case[%d], input: %s, expected: %t, got: %t", i, tc.input, tc.output, !tc.output)
|
t.Errorf("case[%d], input: %s, expected: %t, got: %t", i, tc.input, tc.output, !tc.output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ func TestIsStandardContainerResource(t *testing.T) {
|
|||||||
{"hugepages-2Mi", true},
|
{"hugepages-2Mi", true},
|
||||||
}
|
}
|
||||||
for i, tc := range testCases {
|
for i, tc := range testCases {
|
||||||
if IsStandardContainerResourceName(tc.input) != tc.output {
|
if IsStandardContainerResourceName(core.ResourceName(tc.input)) != tc.output {
|
||||||
t.Errorf("case[%d], input: %s, expected: %t, got: %t", i, tc.input, tc.output, !tc.output)
|
t.Errorf("case[%d], input: %s, expected: %t, got: %t", i, tc.input, tc.output, !tc.output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/core"
|
||||||
"k8s.io/kubernetes/pkg/apis/core/helper"
|
"k8s.io/kubernetes/pkg/apis/core/helper"
|
||||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
|
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
|
||||||
@ -42,18 +43,18 @@ func ValidateResourceRequirements(requirements *v1.ResourceRequirements, fldPath
|
|||||||
for resourceName, quantity := range requirements.Limits {
|
for resourceName, quantity := range requirements.Limits {
|
||||||
fldPath := limPath.Key(string(resourceName))
|
fldPath := limPath.Key(string(resourceName))
|
||||||
// Validate resource name.
|
// Validate resource name.
|
||||||
allErrs = append(allErrs, ValidateContainerResourceName(string(resourceName), fldPath)...)
|
allErrs = append(allErrs, ValidateContainerResourceName(core.ResourceName(resourceName), fldPath)...)
|
||||||
|
|
||||||
// Validate resource quantity.
|
// Validate resource quantity.
|
||||||
allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...)
|
allErrs = append(allErrs, ValidateResourceQuantityValue(core.ResourceName(resourceName), quantity, fldPath)...)
|
||||||
|
|
||||||
}
|
}
|
||||||
for resourceName, quantity := range requirements.Requests {
|
for resourceName, quantity := range requirements.Requests {
|
||||||
fldPath := reqPath.Key(string(resourceName))
|
fldPath := reqPath.Key(string(resourceName))
|
||||||
// Validate resource name.
|
// Validate resource name.
|
||||||
allErrs = append(allErrs, ValidateContainerResourceName(string(resourceName), fldPath)...)
|
allErrs = append(allErrs, ValidateContainerResourceName(core.ResourceName(resourceName), fldPath)...)
|
||||||
// Validate resource quantity.
|
// Validate resource quantity.
|
||||||
allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...)
|
allErrs = append(allErrs, ValidateResourceQuantityValue(core.ResourceName(resourceName), quantity, fldPath)...)
|
||||||
|
|
||||||
// Check that request <= limit.
|
// Check that request <= limit.
|
||||||
limitQuantity, exists := requirements.Limits[resourceName]
|
limitQuantity, exists := requirements.Limits[resourceName]
|
||||||
@ -71,9 +72,9 @@ func ValidateResourceRequirements(requirements *v1.ResourceRequirements, fldPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateContainerResourceName checks the name of resource specified for a container
|
// ValidateContainerResourceName checks the name of resource specified for a container
|
||||||
func ValidateContainerResourceName(value string, fldPath *field.Path) field.ErrorList {
|
func ValidateContainerResourceName(value core.ResourceName, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := validateResourceName(value, fldPath)
|
allErrs := validateResourceName(value, fldPath)
|
||||||
if len(strings.Split(value, "/")) == 1 {
|
if len(strings.Split(string(value), "/")) == 1 {
|
||||||
if !helper.IsStandardContainerResourceName(value) {
|
if !helper.IsStandardContainerResourceName(value) {
|
||||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource for containers"))
|
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource for containers"))
|
||||||
}
|
}
|
||||||
@ -86,7 +87,7 @@ func ValidateContainerResourceName(value string, fldPath *field.Path) field.Erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateResourceQuantityValue enforces that specified quantity is valid for specified resource
|
// ValidateResourceQuantityValue enforces that specified quantity is valid for specified resource
|
||||||
func ValidateResourceQuantityValue(resource string, value resource.Quantity, fldPath *field.Path) field.ErrorList {
|
func ValidateResourceQuantityValue(resource core.ResourceName, value resource.Quantity, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
allErrs = append(allErrs, ValidateNonnegativeQuantity(value, fldPath)...)
|
allErrs = append(allErrs, ValidateNonnegativeQuantity(value, fldPath)...)
|
||||||
if helper.IsIntegerResourceName(resource) {
|
if helper.IsIntegerResourceName(resource) {
|
||||||
@ -108,13 +109,13 @@ func ValidateNonnegativeQuantity(value resource.Quantity, fldPath *field.Path) f
|
|||||||
|
|
||||||
// Validate compute resource typename.
|
// Validate compute resource typename.
|
||||||
// Refer to docs/design/resources.md for more details.
|
// Refer to docs/design/resources.md for more details.
|
||||||
func validateResourceName(value string, fldPath *field.Path) field.ErrorList {
|
func validateResourceName(value core.ResourceName, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := apivalidation.ValidateQualifiedName(value, fldPath)
|
allErrs := apivalidation.ValidateQualifiedName(string(value), fldPath)
|
||||||
if len(allErrs) != 0 {
|
if len(allErrs) != 0 {
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(strings.Split(value, "/")) == 1 {
|
if len(strings.Split(string(value), "/")) == 1 {
|
||||||
if !helper.IsStandardResourceName(value) {
|
if !helper.IsStandardResourceName(value) {
|
||||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource type or fully qualified"))
|
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource type or fully qualified"))
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestValidateResourceRequirements(t *testing.T) {
|
func TestValidateResourceRequirements(t *testing.T) {
|
||||||
@ -158,7 +159,7 @@ func validateNamesAndValuesInDescription(t *testing.T, r v1.ResourceList, errs f
|
|||||||
func TestValidateContainerResourceName(t *testing.T) {
|
func TestValidateContainerResourceName(t *testing.T) {
|
||||||
successCase := []struct {
|
successCase := []struct {
|
||||||
name string
|
name string
|
||||||
ResourceName string
|
ResourceName core.ResourceName
|
||||||
}{{
|
}{{
|
||||||
name: "CPU resource",
|
name: "CPU resource",
|
||||||
ResourceName: "cpu",
|
ResourceName: "cpu",
|
||||||
@ -177,7 +178,7 @@ func TestValidateContainerResourceName(t *testing.T) {
|
|||||||
}}
|
}}
|
||||||
for _, tc := range successCase {
|
for _, tc := range successCase {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
if errs := ValidateContainerResourceName(tc.ResourceName, field.NewPath(tc.ResourceName)); len(errs) != 0 {
|
if errs := ValidateContainerResourceName(tc.ResourceName, field.NewPath(string(tc.ResourceName))); len(errs) != 0 {
|
||||||
t.Errorf("unexpected error: %v", errs)
|
t.Errorf("unexpected error: %v", errs)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -185,7 +186,7 @@ func TestValidateContainerResourceName(t *testing.T) {
|
|||||||
|
|
||||||
errorCase := []struct {
|
errorCase := []struct {
|
||||||
name string
|
name string
|
||||||
ResourceName string
|
ResourceName core.ResourceName
|
||||||
}{{
|
}{{
|
||||||
name: "Invalid standard resource",
|
name: "Invalid standard resource",
|
||||||
ResourceName: "cpu-core",
|
ResourceName: "cpu-core",
|
||||||
@ -198,7 +199,7 @@ func TestValidateContainerResourceName(t *testing.T) {
|
|||||||
}}
|
}}
|
||||||
for _, tc := range errorCase {
|
for _, tc := range errorCase {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
if errs := ValidateContainerResourceName(tc.ResourceName, field.NewPath(tc.ResourceName)); len(errs) == 0 {
|
if errs := ValidateContainerResourceName(tc.ResourceName, field.NewPath(string(tc.ResourceName))); len(errs) == 0 {
|
||||||
t.Errorf("expected error")
|
t.Errorf("expected error")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -7526,8 +7526,7 @@ func TestValidateContainers(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var PodRestartPolicy core.RestartPolicy
|
var PodRestartPolicy core.RestartPolicy = "Always"
|
||||||
PodRestartPolicy = "Always"
|
|
||||||
if errs := validateContainers(successCase, volumeDevices, nil, defaultGracePeriod, field.NewPath("field"), PodValidationOptions{}, &PodRestartPolicy); len(errs) != 0 {
|
if errs := validateContainers(successCase, volumeDevices, nil, defaultGracePeriod, field.NewPath("field"), PodValidationOptions{}, &PodRestartPolicy); len(errs) != 0 {
|
||||||
t.Errorf("expected success: %v", errs)
|
t.Errorf("expected success: %v", errs)
|
||||||
}
|
}
|
||||||
@ -8230,8 +8229,7 @@ func TestValidateInitContainers(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
var PodRestartPolicy core.RestartPolicy
|
var PodRestartPolicy core.RestartPolicy = "Never"
|
||||||
PodRestartPolicy = "Never"
|
|
||||||
if errs := validateInitContainers(successCase, containers, volumeDevices, nil, defaultGracePeriod, field.NewPath("field"), PodValidationOptions{}, &PodRestartPolicy); len(errs) != 0 {
|
if errs := validateInitContainers(successCase, containers, volumeDevices, nil, defaultGracePeriod, field.NewPath("field"), PodValidationOptions{}, &PodRestartPolicy); len(errs) != 0 {
|
||||||
t.Errorf("expected success: %v", errs)
|
t.Errorf("expected success: %v", errs)
|
||||||
}
|
}
|
||||||
@ -18811,7 +18809,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
|||||||
|
|
||||||
func TestValidateResourceNames(t *testing.T) {
|
func TestValidateResourceNames(t *testing.T) {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
input string
|
input core.ResourceName
|
||||||
success bool
|
success bool
|
||||||
expect string
|
expect string
|
||||||
}{
|
}{
|
||||||
@ -18832,8 +18830,8 @@ func TestValidateResourceNames(t *testing.T) {
|
|||||||
{"my.favorite.app.co/_12345", false, ""},
|
{"my.favorite.app.co/_12345", false, ""},
|
||||||
{"my.favorite.app.co/12345_", false, ""},
|
{"my.favorite.app.co/12345_", false, ""},
|
||||||
{"kubernetes.io/..", false, ""},
|
{"kubernetes.io/..", false, ""},
|
||||||
{"kubernetes.io/" + strings.Repeat("a", 63), true, ""},
|
{core.ResourceName("kubernetes.io/" + strings.Repeat("a", 63)), true, ""},
|
||||||
{"kubernetes.io/" + strings.Repeat("a", 64), false, ""},
|
{core.ResourceName("kubernetes.io/" + strings.Repeat("a", 64)), false, ""},
|
||||||
{"kubernetes.io//", false, ""},
|
{"kubernetes.io//", false, ""},
|
||||||
{"kubernetes.io", false, ""},
|
{"kubernetes.io", false, ""},
|
||||||
{"kubernetes.io/will/not/work/", false, ""},
|
{"kubernetes.io/will/not/work/", false, ""},
|
||||||
@ -22211,13 +22209,13 @@ func TestValidateTopologySpreadConstraints(t *testing.T) {
|
|||||||
constraints: []core.TopologySpreadConstraint{
|
constraints: []core.TopologySpreadConstraint{
|
||||||
{MaxSkew: 1, TopologyKey: "k8s.io/zone"},
|
{MaxSkew: 1, TopologyKey: "k8s.io/zone"},
|
||||||
},
|
},
|
||||||
wantFieldErrors: []*field.Error{field.NotSupported(fieldPathWhenUnsatisfiable, core.UnsatisfiableConstraintAction(""), supportedScheduleActions.List())},
|
wantFieldErrors: []*field.Error{field.NotSupported(fieldPathWhenUnsatisfiable, core.UnsatisfiableConstraintAction(""), sets.List(supportedScheduleActions))},
|
||||||
}, {
|
}, {
|
||||||
name: "unsupported scheduling mode",
|
name: "unsupported scheduling mode",
|
||||||
constraints: []core.TopologySpreadConstraint{
|
constraints: []core.TopologySpreadConstraint{
|
||||||
{MaxSkew: 1, TopologyKey: "k8s.io/zone", WhenUnsatisfiable: core.UnsatisfiableConstraintAction("N/A")},
|
{MaxSkew: 1, TopologyKey: "k8s.io/zone", WhenUnsatisfiable: core.UnsatisfiableConstraintAction("N/A")},
|
||||||
},
|
},
|
||||||
wantFieldErrors: []*field.Error{field.NotSupported(fieldPathWhenUnsatisfiable, core.UnsatisfiableConstraintAction("N/A"), supportedScheduleActions.List())},
|
wantFieldErrors: []*field.Error{field.NotSupported(fieldPathWhenUnsatisfiable, core.UnsatisfiableConstraintAction("N/A"), sets.List(supportedScheduleActions))},
|
||||||
}, {
|
}, {
|
||||||
name: "multiple constraints ok with all required fields",
|
name: "multiple constraints ok with all required fields",
|
||||||
constraints: []core.TopologySpreadConstraint{
|
constraints: []core.TopologySpreadConstraint{
|
||||||
@ -22261,7 +22259,7 @@ func TestValidateTopologySpreadConstraints(t *testing.T) {
|
|||||||
NodeTaintsPolicy: &ignore,
|
NodeTaintsPolicy: &ignore,
|
||||||
}},
|
}},
|
||||||
wantFieldErrors: []*field.Error{
|
wantFieldErrors: []*field.Error{
|
||||||
field.NotSupported(nodeAffinityField, &unknown, supportedPodTopologySpreadNodePolicies.List()),
|
field.NotSupported(nodeAffinityField, &unknown, sets.List(supportedPodTopologySpreadNodePolicies)),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "unsupported policy name set on NodeTaintsPolicy",
|
name: "unsupported policy name set on NodeTaintsPolicy",
|
||||||
@ -22273,7 +22271,7 @@ func TestValidateTopologySpreadConstraints(t *testing.T) {
|
|||||||
NodeTaintsPolicy: &unknown,
|
NodeTaintsPolicy: &unknown,
|
||||||
}},
|
}},
|
||||||
wantFieldErrors: []*field.Error{
|
wantFieldErrors: []*field.Error{
|
||||||
field.NotSupported(nodeTaintsField, &unknown, supportedPodTopologySpreadNodePolicies.List()),
|
field.NotSupported(nodeTaintsField, &unknown, sets.List(supportedPodTopologySpreadNodePolicies)),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "key in MatchLabelKeys isn't correctly defined",
|
name: "key in MatchLabelKeys isn't correctly defined",
|
||||||
|
@ -270,7 +270,7 @@ func validateAllowedTopologies(topologies []api.TopologySelectorTerm, fldPath *f
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
rawTopologies := make([]map[string]sets.String, len(topologies))
|
rawTopologies := make([]map[string]sets.Set[string], len(topologies))
|
||||||
for i, term := range topologies {
|
for i, term := range topologies {
|
||||||
idxPath := fldPath.Index(i)
|
idxPath := fldPath.Index(i)
|
||||||
exprMap, termErrs := apivalidation.ValidateTopologySelectorTerm(term, fldPath.Index(i))
|
exprMap, termErrs := apivalidation.ValidateTopologySelectorTerm(term, fldPath.Index(i))
|
||||||
|
@ -164,7 +164,7 @@ func TestNewInvalid(t *testing.T) {
|
|||||||
`Kind "name" is invalid: field[0].name: Not found: "bar"`,
|
`Kind "name" is invalid: field[0].name: Not found: "bar"`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field.NotSupported(field.NewPath("field[0].name"), "bar", nil),
|
field.NotSupported[string](field.NewPath("field[0].name"), "bar", nil),
|
||||||
&metav1.StatusDetails{
|
&metav1.StatusDetails{
|
||||||
Kind: "Kind",
|
Kind: "Kind",
|
||||||
Name: "name",
|
Name: "name",
|
||||||
|
@ -200,12 +200,12 @@ func Invalid(field *Path, value interface{}, detail string) *Error {
|
|||||||
// NotSupported returns a *Error indicating "unsupported value".
|
// NotSupported returns a *Error indicating "unsupported value".
|
||||||
// This is used to report unknown values for enumerated fields (e.g. a list of
|
// This is used to report unknown values for enumerated fields (e.g. a list of
|
||||||
// valid values).
|
// valid values).
|
||||||
func NotSupported(field *Path, value interface{}, validValues []string) *Error {
|
func NotSupported[T ~string](field *Path, value interface{}, validValues []T) *Error {
|
||||||
detail := ""
|
detail := ""
|
||||||
if len(validValues) > 0 {
|
if len(validValues) > 0 {
|
||||||
quotedValues := make([]string, len(validValues))
|
quotedValues := make([]string, len(validValues))
|
||||||
for i, v := range validValues {
|
for i, v := range validValues {
|
||||||
quotedValues[i] = strconv.Quote(v)
|
quotedValues[i] = strconv.Quote(fmt.Sprint(v))
|
||||||
}
|
}
|
||||||
detail = "supported values: " + strings.Join(quotedValues, ", ")
|
detail = "supported values: " + strings.Join(quotedValues, ", ")
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ func TestMakeFuncs(t *testing.T) {
|
|||||||
ErrorTypeInvalid,
|
ErrorTypeInvalid,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
func() *Error { return NotSupported(NewPath("f"), "v", nil) },
|
func() *Error { return NotSupported[string](NewPath("f"), "v", nil) },
|
||||||
ErrorTypeNotSupported,
|
ErrorTypeNotSupported,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user