mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	generic set
This commit is contained in:
		@@ -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,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user