Migrate all strategies to DV

This commit is contained in:
Joe Betz 2026-04-10 15:58:18 -04:00
parent 30c76c1879
commit a0095b5379
No known key found for this signature in database
GPG key ID: 83FEBBE24213FEF6
89 changed files with 336 additions and 340 deletions

View file

@ -24,6 +24,7 @@ import (
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/features"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -34,7 +35,7 @@ import (
// mutatingAdmissionPolicyStrategy implements verification logic for MutatingAdmissionPolicy.
type mutatingAdmissionPolicyStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
authorizer authorizer.Authorizer
resourceResolver resolver.ResourceResolver
@ -43,7 +44,7 @@ type mutatingAdmissionPolicyStrategy struct {
// NewStrategy is the default logic that applies when creating and updating MutatingAdmissionPolicy objects.
func NewStrategy(authorizer authorizer.Authorizer, resourceResolver resolver.ResourceResolver) *mutatingAdmissionPolicyStrategy {
return &mutatingAdmissionPolicyStrategy{
ObjectTyper: legacyscheme.Scheme,
DeclarativeValidation: rest.DeclarativeValidation{Scheme: legacyscheme.Scheme},
NameGenerator: names.SimpleNameGenerator,
authorizer: authorizer,
resourceResolver: resourceResolver,

View file

@ -24,6 +24,7 @@ import (
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/features"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -34,7 +35,7 @@ import (
// MutatingAdmissionPolicyBindingStrategy implements verification logic for MutatingAdmissionPolicyBinding.
type mutatingAdmissionPolicyBindingStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
authorizer authorizer.Authorizer
policyGetter PolicyGetter
@ -50,7 +51,7 @@ type PolicyGetter interface {
// NewStrategy is the default logic that applies when creating and updating MutatingAdmissionPolicyBinding objects.
func NewStrategy(authorizer authorizer.Authorizer, policyGetter PolicyGetter, resourceResolver resolver.ResourceResolver) *mutatingAdmissionPolicyBindingStrategy {
return &mutatingAdmissionPolicyBindingStrategy{
ObjectTyper: legacyscheme.Scheme,
DeclarativeValidation: rest.DeclarativeValidation{Scheme: legacyscheme.Scheme},
NameGenerator: names.SimpleNameGenerator,
authorizer: authorizer,
policyGetter: policyGetter,

View file

@ -23,6 +23,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/features"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -32,12 +33,12 @@ import (
// mutatingWebhookConfigurationStrategy implements verification logic for mutatingWebhookConfiguration.
type mutatingWebhookConfigurationStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating mutatingWebhookConfiguration objects.
var Strategy = mutatingWebhookConfigurationStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = mutatingWebhookConfigurationStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns false because MutatingWebhookConfiguration is cluster-scoped resource.
func (mutatingWebhookConfigurationStrategy) NamespaceScoped() bool {

View file

@ -27,6 +27,7 @@ import (
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/features"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -37,7 +38,7 @@ import (
// validatingAdmissionPolicyStrategy implements verification logic for ValidatingAdmissionPolicy.
type validatingAdmissionPolicyStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
authorizer authorizer.Authorizer
resourceResolver resolver.ResourceResolver
@ -46,7 +47,7 @@ type validatingAdmissionPolicyStrategy struct {
// NewStrategy is the default logic that applies when creating and updating validatingAdmissionPolicy objects.
func NewStrategy(authorizer authorizer.Authorizer, resourceResolver resolver.ResourceResolver) *validatingAdmissionPolicyStrategy {
return &validatingAdmissionPolicyStrategy{
ObjectTyper: legacyscheme.Scheme,
DeclarativeValidation: rest.DeclarativeValidation{Scheme: legacyscheme.Scheme},
NameGenerator: names.SimpleNameGenerator,
authorizer: authorizer,
resourceResolver: resourceResolver,

View file

@ -67,7 +67,7 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
}
for k, tc := range testCases {
t.Run(k, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, &Strategy, tc.expectedErrs)
})
}
}
@ -117,7 +117,7 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
IsResourceRequest: true,
Verb: "update",
})
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, Strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, &Strategy, tc.expectedErrs)
})
}
}

View file

@ -18,7 +18,6 @@ package validatingadmissionpolicybinding
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apiserver/pkg/registry/rest"
apiequality "k8s.io/apimachinery/pkg/api/equality"
@ -36,7 +35,7 @@ import (
// validatingAdmissionPolicyBindingStrategy implements verification logic for ValidatingAdmissionPolicyBinding.
type validatingAdmissionPolicyBindingStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
authorizer authorizer.Authorizer
policyGetter PolicyGetter
@ -54,7 +53,7 @@ type PolicyGetter interface {
// NewStrategy is the default logic that applies when creating and updating ValidatingAdmissionPolicyBinding objects.
func NewStrategy(authorizer authorizer.Authorizer, policyGetter PolicyGetter, resourceResolver resolver.ResourceResolver) *validatingAdmissionPolicyBindingStrategy {
return &validatingAdmissionPolicyBindingStrategy{
ObjectTyper: legacyscheme.Scheme,
DeclarativeValidation: rest.DeclarativeValidation{Scheme: legacyscheme.Scheme},
NameGenerator: names.SimpleNameGenerator,
authorizer: authorizer,
policyGetter: policyGetter,
@ -99,7 +98,7 @@ func (v *validatingAdmissionPolicyBindingStrategy) Validate(ctx context.Context,
errs = append(errs, field.Forbidden(field.NewPath("spec", "paramRef"), err.Error()))
}
}
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, nil, errs, operation.Create)
return errs
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -131,7 +130,7 @@ func (v *validatingAdmissionPolicyBindingStrategy) ValidateUpdate(ctx context.Co
errs = append(errs, field.Forbidden(field.NewPath("spec", "paramRef"), err.Error()))
}
}
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, old, errs, operation.Update)
return errs
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -23,6 +23,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/features"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -32,12 +33,12 @@ import (
// validatingWebhookConfigurationStrategy implements verification logic for validatingWebhookConfiguration.
type validatingWebhookConfigurationStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating validatingWebhookConfiguration objects.
var Strategy = validatingWebhookConfigurationStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = validatingWebhookConfigurationStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns false because ValidatingWebhookConfiguration is cluster-scoped resource.
func (validatingWebhookConfigurationStrategy) NamespaceScoped() bool {

View file

@ -22,6 +22,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/apiserverinternal"
@ -31,12 +32,12 @@ import (
// storageVersionStrategy implements verification logic for StorageVersion.
type storageVersionStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating StorageVersion objects.
var Strategy = storageVersionStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = storageVersionStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns false because all StorageVersion's need to be cluster scoped
func (storageVersionStrategy) NamespaceScoped() bool {

View file

@ -30,13 +30,13 @@ import (
// strategy implements behavior for ConfigMap objects
type strategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating ControllerRevision
// objects via the REST API.
var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = strategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// Strategy should implement rest.RESTCreateStrategy
var _ rest.RESTCreateStrategy = Strategy

View file

@ -34,12 +34,12 @@ import (
// daemonSetStrategy implements verification logic for daemon sets.
type daemonSetStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating DaemonSet objects.
var Strategy = daemonSetStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = daemonSetStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// Make sure we correctly implement the interface.
var _ = rest.GarbageCollectionDeleteStrategy(Strategy)

View file

@ -37,13 +37,13 @@ import (
// deploymentStrategy implements behavior for Deployments.
type deploymentStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Deployment
// objects via the REST API.
var Strategy = deploymentStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = deploymentStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// Make sure we correctly implement the interface.
var _ = rest.GarbageCollectionDeleteStrategy(Strategy)

View file

@ -44,12 +44,12 @@ import (
// rsStrategy implements verification logic for ReplicaSets.
type rsStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating ReplicaSet objects.
var Strategy = rsStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = rsStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// Make sure we correctly implement the interface.
var _ = rest.GarbageCollectionDeleteStrategy(Strategy)

View file

@ -36,12 +36,12 @@ import (
// statefulSetStrategy implements verification logic for Replication StatefulSets.
type statefulSetStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Replication StatefulSet objects.
var Strategy = statefulSetStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = statefulSetStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// Make sure we correctly implement the interface.
var _ = rest.GarbageCollectionDeleteStrategy(Strategy)

View file

@ -82,7 +82,7 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.HPAScaleToZero, tc.enableScaleToZero)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs)
})
}
}
@ -153,7 +153,7 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
IsResourceRequest: true,
Verb: "update",
})
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, Strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, Strategy, tc.expectedErrs)
})
}
}

View file

@ -20,7 +20,6 @@ import (
"context"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
@ -35,13 +34,13 @@ import (
// autoscalerStrategy implements behavior for HorizontalPodAutoscalers
type autoscalerStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating HorizontalPodAutoscaler
// objects via the REST API.
var Strategy = autoscalerStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = autoscalerStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped is true for autoscaler.
func (autoscalerStrategy) NamespaceScoped() bool {
@ -82,12 +81,27 @@ func (autoscalerStrategy) PrepareForCreate(ctx context.Context, obj runtime.Obje
func (autoscalerStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
autoscaler := obj.(*autoscaling.HorizontalPodAutoscaler)
opts := validationOptionsForHorizontalPodAutoscaler(autoscaler, nil)
allErrs := validation.ValidateHorizontalPodAutoscaler(autoscaler, opts)
return validation.ValidateHorizontalPodAutoscaler(autoscaler, opts)
}
// DeclarativeValidationConfig implements rest.DeclarativeValidationConfigurer to supply declarative
// validation options.
func (autoscalerStrategy) DeclarativeValidationConfig(ctx context.Context, obj, oldObj runtime.Object) rest.DeclarativeValidationConfig {
var options []string
if utilfeature.DefaultFeatureGate.Enabled(features.HPAScaleToZero) {
// Pass HPAScaleToZero when the gate is enabled, OR (on update) when the
// existing object already has MinReplicas == 0.
enableScaleToZero := utilfeature.DefaultFeatureGate.Enabled(features.HPAScaleToZero)
if !enableScaleToZero && oldObj != nil {
if oldHPA, ok := oldObj.(*autoscaling.HorizontalPodAutoscaler); ok {
if oldHPA.Spec.MinReplicas != nil && *oldHPA.Spec.MinReplicas == 0 {
enableScaleToZero = true
}
}
}
if enableScaleToZero {
options = append(options, "HPAScaleToZero")
}
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, autoscaler, nil, allErrs, operation.Create, rest.WithOptions(options))
return rest.DeclarativeValidationConfig{Options: options}
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -125,13 +139,7 @@ func (autoscalerStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.O
newHPA := obj.(*autoscaling.HorizontalPodAutoscaler)
oldHPA := old.(*autoscaling.HorizontalPodAutoscaler)
opts := validationOptionsForHorizontalPodAutoscaler(newHPA, oldHPA)
errs := validation.ValidateHorizontalPodAutoscalerUpdate(newHPA, oldHPA, opts)
var options []string
oldHasZeroMinReplicas := oldHPA.Spec.MinReplicas != nil && *oldHPA.Spec.MinReplicas == 0
if utilfeature.DefaultFeatureGate.Enabled(features.HPAScaleToZero) || oldHasZeroMinReplicas {
options = append(options, "HPAScaleToZero")
}
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newHPA, oldHPA, errs, operation.Update, rest.WithOptions(options))
return validation.ValidateHorizontalPodAutoscalerUpdate(newHPA, oldHPA, opts)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -55,7 +55,7 @@ func testDeclarativeValidateForDeclarative(t *testing.T, apiVersion string) {
}
for k, tc := range testCases {
t.Run(k, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs)
})
}
}
@ -93,7 +93,7 @@ func testValidateUpdateForDeclarative(t *testing.T, apiVersion string) {
t.Run(k, func(t *testing.T) {
tc.old.ResourceVersion = "1"
tc.update.ResourceVersion = "2"
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy, tc.expectedErrs)
})
}
}

View file

@ -23,7 +23,6 @@ import (
batchv1beta1 "k8s.io/api/batch/v1beta1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
utilvalidation "k8s.io/apimachinery/pkg/util/validation"
@ -41,12 +40,12 @@ import (
// cronJobStrategy implements verification logic for Replication Controllers.
type cronJobStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating CronJob objects.
var Strategy = cronJobStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = cronJobStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// DefaultGarbageCollectionPolicy returns OrphanDependents for batch/v1beta1 for backwards compatibility,
// and DeleteDependents for all other versions.
@ -113,8 +112,7 @@ func (cronJobStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Ob
func (cronJobStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
cronJob := obj.(*batch.CronJob)
opts := pod.GetValidationOptionsFromPodTemplate(&cronJob.Spec.JobTemplate.Spec.Template, nil)
allErrs := batchvalidation.ValidateCronJobCreate(cronJob, opts)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, nil, allErrs, operation.Create)
return batchvalidation.ValidateCronJobCreate(cronJob, opts)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -147,8 +145,7 @@ func (cronJobStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Obje
oldCronJob := old.(*batch.CronJob)
opts := pod.GetValidationOptionsFromPodTemplate(&newCronJob.Spec.JobTemplate.Spec.Template, &oldCronJob.Spec.JobTemplate.Spec.Template)
allErrs := batchvalidation.ValidateCronJobUpdate(newCronJob, oldCronJob, opts)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newCronJob, oldCronJob, allErrs, operation.Update)
return batchvalidation.ValidateCronJobUpdate(newCronJob, oldCronJob, opts)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -50,12 +50,12 @@ import (
// jobStrategy implements verification logic for Replication Controllers.
type jobStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Replication Controller objects.
var Strategy = jobStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = jobStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// DefaultGarbageCollectionPolicy returns OrphanDependents for batch/v1 for backwards compatibility,
// and DeleteDependents for all other versions.

View file

@ -26,9 +26,9 @@ import (
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
apitesting "k8s.io/kubernetes/pkg/api/testing"
api "k8s.io/kubernetes/pkg/apis/certificates"
"k8s.io/kubernetes/pkg/apis/core"
@ -37,11 +37,6 @@ import (
var apiVersions = []string{"v1", "v1beta1"}
type validationStrategy interface {
Validate(ctx context.Context, obj runtime.Object) field.ErrorList
ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList
}
func TestDeclarativeValidateForDeclarative(t *testing.T) {
for _, apiVersion := range apiVersions {
testDeclarativeValidateForDeclarative(t, apiVersion)
@ -90,7 +85,7 @@ func testDeclarativeValidateForDeclarative(t *testing.T, apiVersion string) {
}
for k, tc := range testCases {
t.Run(k, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs)
})
}
}
@ -188,7 +183,7 @@ func testValidateUpdateForDeclarative(t *testing.T, apiVersion string) {
for _, subresource := range tc.subresources {
t.Run(k+" subresource="+subresource, func(t *testing.T) {
ctx := createContextForSubresource(apiVersion, subresource)
var strategy validationStrategy
var strategy rest.RESTUpdateStrategy
switch subresource {
case "/":
strategy = Strategy
@ -200,7 +195,7 @@ func testValidateUpdateForDeclarative(t *testing.T, apiVersion string) {
tc.old.ResourceVersion = "1"
tc.update.ResourceVersion = "1"
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, strategy, tc.expectedErrs)
})
}
}

View file

@ -20,7 +20,6 @@ import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/api/operation"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
@ -38,13 +37,13 @@ import (
// csrStrategy implements behavior for CSRs
type csrStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// csrStrategy is the default logic that applies when creating and updating
// CSR objects.
var Strategy = csrStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = csrStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped is false for CSRs.
func (csrStrategy) NamespaceScoped() bool {
@ -114,8 +113,7 @@ func (csrStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object
// Validate validates a new CSR. Validation must check for a correct signature.
func (csrStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
csr := obj.(*certificates.CertificateSigningRequest)
allErrs := validation.ValidateCertificateSigningRequestCreate(csr)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, csr, nil, allErrs, operation.Create)
return validation.ValidateCertificateSigningRequestCreate(csr)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -128,8 +126,7 @@ func (csrStrategy) Canonicalize(obj runtime.Object) {}
func (csrStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
oldCSR := old.(*certificates.CertificateSigningRequest)
newCSR := obj.(*certificates.CertificateSigningRequest)
errs := validation.ValidateCertificateSigningRequestUpdate(newCSR, oldCSR)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newCSR, oldCSR, errs, operation.Update)
return validation.ValidateCertificateSigningRequestUpdate(newCSR, oldCSR)
}
// WarningsOnUpdate returns warnings for the given update.
@ -244,8 +241,7 @@ func populateConditionTimestamps(newCSR, oldCSR *certificates.CertificateSigning
func (csrStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
newCSR := obj.(*certificates.CertificateSigningRequest)
oldCSR := old.(*certificates.CertificateSigningRequest)
errs := validation.ValidateCertificateSigningRequestStatusUpdate(newCSR, oldCSR)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newCSR, oldCSR, errs, operation.Update)
return validation.ValidateCertificateSigningRequestStatusUpdate(newCSR, oldCSR)
}
// WarningsOnUpdate returns warnings for the given update.
@ -299,8 +295,7 @@ func (csrApprovalStrategy) PrepareForUpdate(ctx context.Context, obj, old runtim
func (csrApprovalStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
newCSR := obj.(*certificates.CertificateSigningRequest)
oldCSR := old.(*certificates.CertificateSigningRequest)
errs := validation.ValidateCertificateSigningRequestApprovalUpdate(newCSR, oldCSR)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newCSR, oldCSR, errs, operation.Update)
return validation.ValidateCertificateSigningRequestApprovalUpdate(newCSR, oldCSR)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -32,12 +32,12 @@ import (
// strategy implements behavior for ClusterTrustBundles.
type strategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the create, update, and delete strategy for ClusterTrustBundles.
var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = strategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
var _ rest.RESTCreateStrategy = Strategy
var _ rest.RESTUpdateStrategy = Strategy

View file

@ -41,7 +41,7 @@ import (
// strategy implements behavior for PodCertificateRequests.
type Strategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
@ -51,8 +51,8 @@ var _ rest.RESTDeleteStrategy = (*Strategy)(nil)
func NewStrategy() *Strategy {
return &Strategy{
ObjectTyper: legacyscheme.Scheme,
NameGenerator: names.SimpleNameGenerator,
DeclarativeValidation: rest.DeclarativeValidation{Scheme: legacyscheme.Scheme},
NameGenerator: names.SimpleNameGenerator,
}
}

View file

@ -21,6 +21,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -31,12 +32,12 @@ import (
// leaseStrategy implements verification logic for Leases.
type leaseStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Lease objects.
var Strategy = leaseStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = leaseStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns true because all Lease' need to be within a namespace.
func (leaseStrategy) NamespaceScoped() bool {

View file

@ -25,6 +25,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -34,12 +35,12 @@ import (
// LeaseCandidateStrategy implements verification logic for leasecandidates.
type LeaseCandidateStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating leasecandidate objects.
var Strategy = LeaseCandidateStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = LeaseCandidateStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns true because all leasecandidate' need to be within a namespace.
func (LeaseCandidateStrategy) NamespaceScoped() bool {

View file

@ -35,13 +35,13 @@ import (
// strategy implements behavior for ConfigMap objects
type strategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating ConfigMap
// objects via the REST API.
var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = strategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// Strategy should implement rest.RESTCreateStrategy
var _ rest.RESTCreateStrategy = Strategy

View file

@ -22,6 +22,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
utilvalidation "k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
api "k8s.io/kubernetes/pkg/apis/core"
@ -31,13 +32,13 @@ import (
// endpointsStrategy implements behavior for Endpoints
type endpointsStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Endpoint
// objects via the REST API.
var Strategy = endpointsStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = endpointsStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped is true for endpoints.
func (endpointsStrategy) NamespaceScoped() bool {

View file

@ -36,13 +36,13 @@ import (
)
type eventStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// Event objects via the REST API.
var Strategy = eventStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = eventStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (eventStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy {
return rest.Unsupported

View file

@ -22,6 +22,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
api "k8s.io/kubernetes/pkg/apis/core"
@ -29,13 +30,13 @@ import (
)
type limitrangeStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// LimitRange objects via the REST API.
var Strategy = limitrangeStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = limitrangeStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (limitrangeStrategy) NamespaceScoped() bool {
return true

View file

@ -26,6 +26,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
apistorage "k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -36,13 +37,13 @@ import (
// namespaceStrategy implements behavior for Namespaces
type namespaceStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Namespace
// objects via the REST API.
var Strategy = namespaceStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = namespaceStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped is false for namespaces.
func (namespaceStrategy) NamespaceScoped() bool {

View file

@ -33,6 +33,7 @@ import (
utilvalidation "k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
pkgstorage "k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/names"
utilfeature "k8s.io/apiserver/pkg/util/feature"
@ -46,13 +47,13 @@ import (
// nodeStrategy implements behavior for nodes
type nodeStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Nodes is the default logic that applies when creating and updating Node
// objects.
var Strategy = nodeStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = nodeStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped is false for nodes.
func (nodeStrategy) NamespaceScoped() bool {

View file

@ -26,6 +26,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -38,13 +39,13 @@ import (
// persistentvolumeStrategy implements behavior for PersistentVolume objects
type persistentvolumeStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating PersistentVolume
// objects via the REST API.
var Strategy = persistentvolumeStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = persistentvolumeStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (persistentvolumeStrategy) NamespaceScoped() bool {
return false

View file

@ -25,6 +25,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/names"
"sigs.k8s.io/structured-merge-diff/v6/fieldpath"
@ -37,13 +38,13 @@ import (
// persistentvolumeclaimStrategy implements behavior for PersistentVolumeClaim objects
type persistentvolumeclaimStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating PersistentVolumeClaim
// objects via the REST API.
var Strategy = persistentvolumeclaimStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = persistentvolumeclaimStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (persistentvolumeclaimStrategy) NamespaceScoped() bool {
return true

View file

@ -42,6 +42,7 @@ import (
"k8s.io/apimachinery/pkg/util/validation/field"
apiserverfeatures "k8s.io/apiserver/pkg/features"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/names"
utilfeature "k8s.io/apiserver/pkg/util/feature"
@ -58,13 +59,13 @@ import (
// podStrategy implements behavior for Pods
type podStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Pod
// objects via the REST API.
var Strategy = podStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = podStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped is true for pods.
func (podStrategy) NamespaceScoped() bool {

View file

@ -22,6 +22,7 @@ import (
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/api/pod"
@ -31,13 +32,13 @@ import (
// podTemplateStrategy implements behavior for PodTemplates
type podTemplateStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating PodTemplate
// objects via the REST API.
var Strategy = podTemplateStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = podTemplateStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped is true for pod templates.
func (podTemplateStrategy) NamespaceScoped() bool {

View file

@ -189,7 +189,7 @@ func TestDeclarativeValidateForDeclarative(t *testing.T) {
}
for k, tc := range testCases {
t.Run(k, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs)
})
}
}
@ -274,7 +274,7 @@ func TestValidateUpdateForDeclarative(t *testing.T) {
t.Run(k, func(t *testing.T) {
tc.old.ObjectMeta.ResourceVersion = "1"
tc.update.ObjectMeta.ResourceVersion = "1"
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy, tc.expectedErrs)
})
}
}

View file

@ -314,7 +314,8 @@ func (i *scaleUpdatedObjectInfo) UpdatedObject(ctx context.Context, oldObj runti
}
errs := validation.ValidateScale(scale)
errs = rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, scale, oldScale, errs, operation.Update, rest.WithSubresourceMapper(i.scaleGVKMapper))
dv := rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}
errs = dv.ValidateDeclaratively(ctx, scale, oldScale, errs, operation.Update, rest.DeclarativeValidationConfig{SubresourceGVKMapper: i.scaleGVKMapper})
if len(errs) > 0 {
return nil, errors.NewInvalid(autoscaling.Kind("Scale"), replicationcontroller.Name, errs)

View file

@ -28,7 +28,6 @@ import (
corev1 "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
@ -49,12 +48,12 @@ import (
// rcStrategy implements verification logic for Replication Controllers.
type rcStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Replication Controller objects.
var Strategy = rcStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = rcStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// DefaultGarbageCollectionPolicy returns OrphanDependents for v1 for backwards compatibility,
// and DeleteDependents for all other versions.
@ -127,8 +126,7 @@ func (rcStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorL
opts := pod.GetValidationOptionsFromPodTemplate(controller.Spec.Template, nil)
// Run imperative validation
allErrs := corevalidation.ValidateReplicationController(controller, opts)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, controller, nil, allErrs, operation.Create)
return corevalidation.ValidateReplicationController(controller, opts)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -177,7 +175,7 @@ func (rcStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) f
}
}
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newRc, oldRc, errs, operation.Update)
return errs
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -22,6 +22,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
api "k8s.io/kubernetes/pkg/apis/core"
@ -31,13 +32,13 @@ import (
// resourcequotaStrategy implements behavior for ResourceQuota objects
type resourcequotaStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating ResourceQuota
// objects via the REST API.
var Strategy = resourcequotaStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = resourcequotaStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped is true for resourcequotas.
func (resourcequotaStrategy) NamespaceScoped() bool {

View file

@ -36,13 +36,13 @@ import (
// strategy implements behavior for Secret objects
type strategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Secret
// objects via the REST API.
var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = strategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
var _ = rest.RESTCreateStrategy(Strategy)

View file

@ -28,6 +28,7 @@ import (
utilvalidation "k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
pkgstorage "k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -40,13 +41,13 @@ import (
// svcStrategy implements behavior for Services
type svcStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Services
// objects via the REST API.
var Strategy = svcStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = svcStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped is true for services.
func (svcStrategy) NamespaceScoped() bool {

View file

@ -22,6 +22,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
api "k8s.io/kubernetes/pkg/apis/core"
@ -31,13 +32,13 @@ import (
// strategy implements behavior for ServiceAccount objects
type strategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating ServiceAccount
// objects via the REST API.
var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = strategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (strategy) NamespaceScoped() bool {
return true

View file

@ -85,7 +85,7 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs)
})
}
}
@ -149,7 +149,7 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
})
tc.oldObj.ResourceVersion = "1"
tc.updateObj.ResourceVersion = "2"
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, Strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, Strategy, tc.expectedErrs)
})
}
}

View file

@ -24,7 +24,6 @@ import (
discoveryv1 "k8s.io/api/discovery/v1"
discoveryv1beta1 "k8s.io/api/discovery/v1beta1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/operation"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -46,12 +45,12 @@ import (
// endpointSliceStrategy implements verification logic for Replication.
type endpointSliceStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Replication EndpointSlice objects.
var Strategy = endpointSliceStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = endpointSliceStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns true because all EndpointSlices need to be within a namespace.
func (endpointSliceStrategy) NamespaceScoped() bool {
@ -93,8 +92,7 @@ func (endpointSliceStrategy) PrepareForUpdate(ctx context.Context, obj, old runt
// Validate validates a new EndpointSlice.
func (endpointSliceStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
endpointSlice := obj.(*discovery.EndpointSlice)
allErrs := validation.ValidateEndpointSliceCreate(endpointSlice)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, endpointSlice, nil, allErrs, operation.Create)
return validation.ValidateEndpointSliceCreate(endpointSlice)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -122,8 +120,7 @@ func (endpointSliceStrategy) AllowCreateOnUpdate() bool {
func (endpointSliceStrategy) ValidateUpdate(ctx context.Context, new, old runtime.Object) field.ErrorList {
newEPS := new.(*discovery.EndpointSlice)
oldEPS := old.(*discovery.EndpointSlice)
allErrs := validation.ValidateEndpointSliceUpdate(newEPS, oldEPS)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newEPS, oldEPS, allErrs, operation.Update)
return validation.ValidateEndpointSliceUpdate(newEPS, oldEPS)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -22,6 +22,7 @@ import (
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/flowcontrol"
@ -31,12 +32,12 @@ import (
// flowSchemaStrategy implements verification logic for FlowSchema.
type flowSchemaStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating flow schema objects.
var Strategy = flowSchemaStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = flowSchemaStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns false because all PriorityClasses are global.
func (flowSchemaStrategy) NamespaceScoped() bool {

View file

@ -107,7 +107,7 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs)
})
}
}
@ -183,7 +183,7 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
IsResourceRequest: true,
Verb: "update",
})
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy, tc.expectedErrs)
})
}
}

View file

@ -20,7 +20,6 @@ import (
"context"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field"
@ -35,12 +34,12 @@ import (
// priorityLevelConfigurationStrategy implements verification logic for priority level configurations.
type priorityLevelConfigurationStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating priority level configuration objects.
var Strategy = priorityLevelConfigurationStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = priorityLevelConfigurationStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns false because all PriorityClasses are global.
func (priorityLevelConfigurationStrategy) NamespaceScoped() bool {
@ -98,8 +97,7 @@ func (priorityLevelConfigurationStrategy) Validate(ctx context.Context, obj runt
// all servers are at 1.29+ and will honor the zero value correctly.
plc := obj.(*flowcontrol.PriorityLevelConfiguration)
opts := validation.PriorityLevelValidationOptions{}
allErrs := validation.ValidatePriorityLevelConfiguration(plc, getRequestGroupVersion(ctx), opts)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, plc, nil, allErrs, operation.Create)
return validation.ValidatePriorityLevelConfiguration(plc, getRequestGroupVersion(ctx), opts)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -123,7 +121,7 @@ func (priorityLevelConfigurationStrategy) AllowCreateOnUpdate() bool {
// ValidateUpdate is the default update validation for an end user.
func (priorityLevelConfigurationStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
newPL := obj.(*flowcontrol.PriorityLevelConfiguration)
oldPL := old.(*flowcontrol.PriorityLevelConfiguration)
_ = old.(*flowcontrol.PriorityLevelConfiguration)
// 1.28 server is not aware of the roundtrip annotation, and will
// default any 0 value persisted (for the NominalConcurrencyShares
@ -133,8 +131,7 @@ func (priorityLevelConfigurationStrategy) ValidateUpdate(ctx context.Context, ob
// via v1 or v1beta3(with the roundtrip annotation) until we know
// all servers are at 1.29+ and will honor the zero value correctly.
opts := validation.PriorityLevelValidationOptions{}
allErrs := validation.ValidatePriorityLevelConfiguration(newPL, getRequestGroupVersion(ctx), opts)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newPL, oldPL, allErrs, operation.Update)
return validation.ValidatePriorityLevelConfiguration(newPL, getRequestGroupVersion(ctx), opts)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -24,6 +24,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
utilvalidation "k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/networking"
@ -37,12 +38,12 @@ const (
// ingressStrategy implements verification logic for Replication Ingress.
type ingressStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Replication Ingress objects.
var Strategy = ingressStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = ingressStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns true because all Ingress' need to be within a namespace.
func (ingressStrategy) NamespaceScoped() bool {

View file

@ -76,7 +76,7 @@ func TestDeclarativeValidateParameter(t *testing.T) {
t,
ctx,
&tc.input,
Strategy.Validate,
Strategy,
tc.expectedErrs,
)
})
@ -155,7 +155,7 @@ func TestDeclarativeValidateUpdateParameters(t *testing.T) {
ctx,
&tc.updateObj,
&tc.oldObj,
Strategy.ValidateUpdate,
Strategy,
tc.expectedErrs,
)
})

View file

@ -18,7 +18,7 @@ package ingressclass
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apiserver/pkg/registry/rest"
apiequality "k8s.io/apimachinery/pkg/api/equality"
@ -33,13 +33,13 @@ import (
// ingressClassStrategy implements verification logic for IngressClass
// resources.
type ingressClassStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// IngressClass objects.
var Strategy = ingressClassStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = ingressClassStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns false because IngressClass is a non-namespaced
// resource.
@ -69,8 +69,7 @@ func (ingressClassStrategy) PrepareForUpdate(ctx context.Context, obj, old runti
// Validate validates a new IngressClass.
func (ingressClassStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
ingressClass := obj.(*networking.IngressClass)
allErrs := validation.ValidateIngressClass(ingressClass)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, ingressClass, nil, allErrs, operation.Create)
return validation.ValidateIngressClass(ingressClass)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -93,8 +92,7 @@ func (ingressClassStrategy) ValidateUpdate(ctx context.Context, obj, old runtime
newIngressClass := obj.(*networking.IngressClass)
oldIngressClass := old.(*networking.IngressClass)
allErrs := validation.ValidateIngressClassUpdate(newIngressClass, oldIngressClass)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newIngressClass, oldIngressClass, allErrs, operation.Update)
return validation.ValidateIngressClassUpdate(newIngressClass, oldIngressClass)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -74,7 +74,7 @@ func TestDeclarativeValidateIPAddress(t *testing.T) {
t,
ctx,
&tc.input,
Strategy.Validate,
Strategy,
tc.expectedErrs,
)
})
@ -168,7 +168,7 @@ func TestDeclarativeValidateIPAddressUpdate(t *testing.T) {
ctx,
&tc.updateObj,
&tc.oldObj,
Strategy.ValidateUpdate,
Strategy,
tc.expectedErrs,
)
})

View file

@ -19,7 +19,6 @@ package ipaddress
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
@ -31,7 +30,7 @@ import (
// ipAddressStrategy implements verification logic for Replication.
type ipAddressStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
@ -43,7 +42,7 @@ func (noopNameGenerator) GenerateName(base string) string {
}
// Strategy is the default logic that applies when creating and updating Replication IPAddress objects.
var Strategy = ipAddressStrategy{legacyscheme.Scheme, noopNameGenerator{}}
var Strategy = ipAddressStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, noopNameGenerator{}}
// Strategy should implement rest.RESTCreateStrategy
var _ rest.RESTCreateStrategy = Strategy
@ -73,8 +72,7 @@ func (ipAddressStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
// Validate validates a new IPAddress.
func (ipAddressStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
ipAddress := obj.(*networking.IPAddress)
err := validation.ValidateIPAddress(ipAddress)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, ipAddress, nil, err, operation.Create)
return validation.ValidateIPAddress(ipAddress)
}
// Canonicalize normalizes the object after validation.
@ -92,7 +90,7 @@ func (ipAddressStrategy) ValidateUpdate(ctx context.Context, new, old runtime.Ob
oldIPAddress := old.(*networking.IPAddress)
errList := validation.ValidateIPAddress(newIPAddress)
errList = append(errList, validation.ValidateIPAddressUpdate(newIPAddress, oldIPAddress)...)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newIPAddress, oldIPAddress, errList, operation.Update)
return errList
}
// AllowUnconditionalUpdate is the default update policy for IPAddress objects.

View file

@ -79,7 +79,7 @@ func TestDeclarativeValidateIPBlockCIDR(t *testing.T) {
t,
ctx,
&tc.input,
Strategy.Validate,
Strategy,
tc.expectedErrs,
)
})
@ -147,7 +147,7 @@ func TestDeclarativeValidateIPBlockCIDRUpdate(t *testing.T) {
ctx,
&tc.updateObj,
&tc.oldObj,
Strategy.ValidateUpdate,
Strategy,
tc.expectedErrs,
)
})

View file

@ -18,7 +18,6 @@ package networkpolicy
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apiserver/pkg/registry/rest"
"reflect"
@ -33,12 +32,12 @@ import (
// networkPolicyStrategy implements verification logic for NetworkPolicies
type networkPolicyStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating NetworkPolicy objects.
var Strategy = networkPolicyStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = networkPolicyStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns true because all NetworkPolicies need to be within a namespace.
func (networkPolicyStrategy) NamespaceScoped() bool {
@ -68,9 +67,7 @@ func (networkPolicyStrategy) PrepareForUpdate(ctx context.Context, obj, old runt
func (networkPolicyStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
networkPolicy := obj.(*networking.NetworkPolicy)
ops := validation.ValidationOptionsForNetworking(networkPolicy, nil)
allErrs := validation.ValidateNetworkPolicy(networkPolicy, ops)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, networkPolicy, nil, allErrs, operation.Create)
return validation.ValidateNetworkPolicy(networkPolicy, ops)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -89,8 +86,7 @@ func (networkPolicyStrategy) AllowCreateOnUpdate() bool {
// ValidateUpdate is the default update validation for an end user.
func (networkPolicyStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
opts := validation.ValidationOptionsForNetworking(obj.(*networking.NetworkPolicy), old.(*networking.NetworkPolicy))
allErrs := validation.ValidateNetworkPolicyUpdate(obj.(*networking.NetworkPolicy), old.(*networking.NetworkPolicy), opts)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, old, allErrs, operation.Update)
return validation.ValidateNetworkPolicyUpdate(obj.(*networking.NetworkPolicy), old.(*networking.NetworkPolicy), opts)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -35,12 +35,12 @@ import (
// serviceCIDRStrategy implements verification logic for ServiceCIDR allocators.
type serviceCIDRStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Replication ServiceCIDR objects.
var Strategy = serviceCIDRStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = serviceCIDRStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// Strategy should implement rest.RESTCreateStrategy
var _ rest.RESTCreateStrategy = Strategy

View file

@ -102,7 +102,7 @@ func TestRuntimeClass_DeclarativeValidate_Create(t *testing.T) {
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.obj, Strategy.Validate, tc.expectedErrs,
apitesting.VerifyValidationEquivalence(t, ctx, &tc.obj, Strategy, tc.expectedErrs,
apitesting.WithNormalizationRules(validation.NodeNormalizationRules...))
})
}
@ -148,7 +148,7 @@ func TestRuntimeClass_DeclarativeValidate_Update(t *testing.T) {
t.Run(name, func(t *testing.T) {
tc.oldObj.ObjectMeta.ResourceVersion = "1"
tc.newObj.ObjectMeta.ResourceVersion = "1"
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.newObj, &tc.oldObj, Strategy.ValidateUpdate, tc.expectedErrs, apitesting.WithNormalizationRules(validation.NodeNormalizationRules...))
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.newObj, &tc.oldObj, Strategy, tc.expectedErrs, apitesting.WithNormalizationRules(validation.NodeNormalizationRules...))
})
}
})

View file

@ -18,7 +18,6 @@ package runtimeclass
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
@ -32,12 +31,12 @@ import (
// strategy implements verification logic for RuntimeClass.
type strategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating RuntimeClass objects.
var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = strategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// Strategy should implement rest.RESTCreateStrategy
var _ rest.RESTCreateStrategy = Strategy
@ -71,9 +70,13 @@ func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
// Validate validates a new RuntimeClass. Validation must check for a correct signature.
func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
runtimeClass := obj.(*node.RuntimeClass)
allErrs := validation.ValidateRuntimeClass(runtimeClass)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, runtimeClass, nil, allErrs, operation.Create, rest.WithNormalizationRules(validation.NodeNormalizationRules))
return validation.ValidateRuntimeClass(runtimeClass)
}
// DeclarativeValidationConfig implements rest.DeclarativeValidationConfigurer to supply declarative
// validation options to the generic BeforeCreate/BeforeUpdate code path.
func (strategy) DeclarativeValidationConfig(ctx context.Context, obj, oldObj runtime.Object) rest.DeclarativeValidationConfig {
return rest.DeclarativeValidationConfig{NormalizationRules: validation.NodeNormalizationRules}
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -91,8 +94,7 @@ func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) fie
newObj := obj.(*node.RuntimeClass)
errorList := validation.ValidateRuntimeClass(newObj)
errorList = append(errorList, validation.ValidateRuntimeClassUpdate(newObj, old.(*node.RuntimeClass))...)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newObj, old, errorList, operation.Update, rest.WithNormalizationRules(validation.NodeNormalizationRules))
return errorList
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -25,6 +25,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/policy"
@ -34,12 +35,12 @@ import (
// podDisruptionBudgetStrategy implements verification logic for PodDisruptionBudgets.
type podDisruptionBudgetStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating PodDisruptionBudget objects.
var Strategy = podDisruptionBudgetStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = podDisruptionBudgetStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns true because all PodDisruptionBudget' need to be within a namespace.
func (podDisruptionBudgetStrategy) NamespaceScoped() bool {

View file

@ -62,7 +62,7 @@ func testDeclarativeValidateForDeclarative(t *testing.T, apiVersion string) {
}
for k, tc := range testCases {
t.Run(k, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs)
})
}
}
@ -100,7 +100,7 @@ func testValidateUpdateForDeclarative(t *testing.T, apiVersion string) {
t.Run(k, func(t *testing.T) {
tc.old.ResourceVersion = "1"
tc.update.ResourceVersion = "2"
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy, tc.expectedErrs)
})
}
}

View file

@ -19,7 +19,6 @@ package clusterrole
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
@ -32,13 +31,13 @@ import (
// strategy implements behavior for ClusterRoles
type strategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// ClusterRole objects.
var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = strategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// Strategy should implement rest.RESTCreateStrategy
var _ rest.RESTCreateStrategy = Strategy
@ -76,9 +75,7 @@ func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorLis
opts := validation.ClusterRoleValidationOptions{
AllowInvalidLabelValueInSelector: false,
}
allErrs := validation.ValidateClusterRole(clusterRole, opts)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, clusterRole, nil, allErrs, operation.Create)
return validation.ValidateClusterRole(clusterRole, opts)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -96,9 +93,7 @@ func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) fie
opts := validation.ClusterRoleValidationOptions{
AllowInvalidLabelValueInSelector: hasInvalidLabelValueInLabelSelector(oldObj),
}
errs := validation.ValidateClusterRoleUpdate(newObj, oldObj, opts)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newObj, oldObj, errs, operation.Update)
return validation.ValidateClusterRoleUpdate(newObj, oldObj, opts)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -30,13 +30,13 @@ import (
// strategy implements behavior for ClusterRoleBindings
type strategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// strategy is the default logic that applies when creating and updating
// ClusterRoleBinding objects.
var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = strategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// Strategy should implement rest.RESTCreateStrategy
var _ rest.RESTCreateStrategy = Strategy

View file

@ -69,7 +69,7 @@ func testDeclarativeValidateForDeclarative(t *testing.T, apiVersion string) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs)
})
}
}
@ -113,7 +113,7 @@ func testValidateUpdateForDeclarative(t *testing.T, apiVersion string) {
t.Run(name, func(t *testing.T) {
tc.old.ResourceVersion = "1"
tc.update.ResourceVersion = "2"
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy, tc.expectedErrs)
})
}
}

View file

@ -19,7 +19,6 @@ package role
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
@ -31,13 +30,13 @@ import (
// strategy implements behavior for Roles
type strategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// Role objects.
var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = strategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// Strategy should implement rest.RESTCreateStrategy
var _ rest.RESTCreateStrategy = Strategy
@ -72,8 +71,7 @@ func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
// Validate validates a new Role. Validation must check for a correct signature.
func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
role := obj.(*rbac.Role)
allErrs := validation.ValidateRole(role)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, role, nil, allErrs, operation.Create)
return validation.ValidateRole(role)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -88,8 +86,7 @@ func (strategy) Canonicalize(obj runtime.Object) {
func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
newObj := obj.(*rbac.Role)
oldObj := old.(*rbac.Role)
errs := validation.ValidateRoleUpdate(newObj, oldObj)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newObj, oldObj, errs, operation.Update)
return validation.ValidateRoleUpdate(newObj, oldObj)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -99,7 +99,7 @@ func testDeclarativeValidateForDeclarative(t *testing.T, apiVersion string) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs)
})
}
}

View file

@ -19,7 +19,6 @@ package rolebinding
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
@ -31,13 +30,13 @@ import (
// strategy implements behavior for RoleBindings
type strategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// strategy is the default logic that applies when creating and updating
// RoleBinding objects.
var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = strategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// Strategy should implement rest.RESTCreateStrategy
var _ rest.RESTCreateStrategy = Strategy
@ -72,8 +71,7 @@ func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
// Validate validates a new RoleBinding. Validation must check for a correct signature.
func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
roleBinding := obj.(*rbac.RoleBinding)
allErrs := validation.ValidateRoleBinding(roleBinding)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, roleBinding, nil, allErrs, operation.Create)
return validation.ValidateRoleBinding(roleBinding)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -90,9 +88,7 @@ func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) fie
newRoleBinding := obj.(*rbac.RoleBinding)
oldRoleBinding := old.(*rbac.RoleBinding)
allErrs := validation.ValidateRoleBindingUpdate(newRoleBinding, oldRoleBinding)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newRoleBinding, oldRoleBinding, allErrs, operation.Update)
return validation.ValidateRoleBindingUpdate(newRoleBinding, oldRoleBinding)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -142,7 +142,7 @@ func TestDeclarativeValidate(t *testing.T) {
for k, tc := range testCases {
t.Run(k, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, strategy, tc.expectedErrs)
})
}
})
@ -247,7 +247,7 @@ func TestDeclarativeValidateUpdate(t *testing.T) {
t.Run(k, func(t *testing.T) {
tc.old.ResourceVersion = "1"
tc.update.ResourceVersion = "1"
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, strategy, tc.expectedErrs)
})
}
})

View file

@ -20,7 +20,6 @@ import (
"context"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
@ -34,11 +33,11 @@ import (
// deviceClassStrategy implements behavior for DeviceClass objects
type deviceClassStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
var Strategy = deviceClassStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = deviceClassStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (deviceClassStrategy) NamespaceScoped() bool {
return false
@ -52,9 +51,7 @@ func (deviceClassStrategy) PrepareForCreate(ctx context.Context, obj runtime.Obj
func (deviceClassStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
deviceClass := obj.(*resource.DeviceClass)
errorList := validation.ValidateDeviceClass(deviceClass)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, deviceClass, nil, errorList, operation.Create)
return validation.ValidateDeviceClass(deviceClass)
}
func (deviceClassStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
@ -83,8 +80,7 @@ func (deviceClassStrategy) PrepareForUpdate(ctx context.Context, obj, old runtim
func (deviceClassStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
newClass := obj.(*resource.DeviceClass)
oldClass := old.(*resource.DeviceClass)
errorList := validation.ValidateDeviceClassUpdate(newClass, oldClass)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newClass, oldClass, errorList, operation.Update)
return validation.ValidateDeviceClassUpdate(newClass, oldClass)
}
func (deviceClassStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {

View file

@ -24,6 +24,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/resource"
@ -33,12 +34,12 @@ import (
// deviceTaintRuleStrategy implements behavior for DeviceTaintRule objects
type deviceTaintRuleStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
var (
Strategy = &deviceTaintRuleStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
Strategy = &deviceTaintRuleStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
StatusStrategy = &deviceTaintRuleStatusStrategy{deviceTaintRuleStrategy: Strategy}
)

View file

@ -502,7 +502,7 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
}
for k, tc := range testCases {
t.Run(k, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs, apitesting.WithNormalizationRules(validation.ResourceNormalizationRules...))
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs, apitesting.WithNormalizationRules(validation.ResourceNormalizationRules...))
})
}
}
@ -820,7 +820,7 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
t.Run(k, func(t *testing.T) {
tc.old.ResourceVersion = "1"
tc.update.ResourceVersion = "2"
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy.ValidateUpdate, tc.expectedErrs, apitesting.WithNormalizationRules(validation.ResourceNormalizationRules...))
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, Strategy, tc.expectedErrs, apitesting.WithNormalizationRules(validation.ResourceNormalizationRules...))
})
}
}
@ -1437,7 +1437,7 @@ func testValidateStatusUpdateForDeclarative(t *testing.T, apiVersion string) {
t.Run(k, func(t *testing.T) {
tc.old.ObjectMeta.ResourceVersion = "1"
tc.update.ObjectMeta.ResourceVersion = "1"
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, strategy.ValidateUpdate, tc.expectedErrs, apitesting.WithSubResources("status"))
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, strategy, tc.expectedErrs, apitesting.WithSubResources("status"))
})
}
}

View file

@ -22,7 +22,6 @@ import (
"sigs.k8s.io/structured-merge-diff/v6/fieldpath"
"k8s.io/apimachinery/pkg/api/operation"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
@ -49,7 +48,7 @@ import (
// resourceclaimStrategy implements behavior for ResourceClaim objects
type resourceclaimStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
nsClient v1.NamespaceInterface
authorizer authorizer.Authorizer
@ -58,7 +57,7 @@ type resourceclaimStrategy struct {
// NewStrategy is the default logic that applies when creating and updating ResourceClaim objects.
func NewStrategy(nsClient v1.NamespaceInterface, authorizer authorizer.Authorizer) *resourceclaimStrategy {
return &resourceclaimStrategy{
legacyscheme.Scheme,
rest.DeclarativeValidation{Scheme: legacyscheme.Scheme},
names.SimpleNameGenerator,
nsClient,
authorizer,
@ -104,7 +103,23 @@ func (s *resourceclaimStrategy) Validate(ctx context.Context, obj runtime.Object
allErrs := resourceutils.AuthorizedForAdmin(ctx, claim.Spec.Devices.Requests, claim.Namespace, s.nsClient)
allErrs = append(allErrs, validation.ValidateResourceClaim(claim)...)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, claim, nil, allErrs, operation.Create, rest.WithNormalizationRules(validation.ResourceNormalizationRules))
return allErrs
}
// DeclarativeValidationConfig implements rest.DeclarativeValidationConfigurer to supply declarative
// validation options to the generic BeforeCreate/BeforeUpdate code path.
//
// TODO: Behavior drift introduced when wiring declarative validation
// universally: the status substrategy embeds *resourceclaimStrategy and now
// inherits this method, so status updates pick up
// WithNormalizationRules(ResourceNormalizationRules). Previously the
// pre-migration inline declarative-validation call on the status subresource
// did NOT pass normalization rules. The change is additive (mismatch
// comparisons are stricter on status updates) but should be reviewed; if the
// status subresource should not use these rules, override
// ValidationConfig on resourceclaimStatusStrategy.
func (*resourceclaimStrategy) DeclarativeValidationConfig(ctx context.Context, obj, oldObj runtime.Object) rest.DeclarativeValidationConfig {
return rest.DeclarativeValidationConfig{NormalizationRules: validation.ResourceNormalizationRules}
}
func (*resourceclaimStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
@ -130,8 +145,7 @@ func (s *resourceclaimStrategy) ValidateUpdate(ctx context.Context, obj, old run
newClaim := obj.(*resource.ResourceClaim)
oldClaim := old.(*resource.ResourceClaim)
// AuthorizedForAdmin isn't needed here because the spec is immutable.
errorList := validation.ValidateResourceClaimUpdate(newClaim, oldClaim)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newClaim, oldClaim, errorList, operation.Update, rest.WithNormalizationRules(validation.ResourceNormalizationRules))
return validation.ValidateResourceClaimUpdate(newClaim, oldClaim)
}
func (*resourceclaimStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
@ -209,7 +223,7 @@ func (r *resourceclaimStatusStrategy) ValidateUpdate(ctx context.Context, obj, o
}
}
errs = append(errs, validation.ValidateResourceClaimStatusUpdate(newClaim, oldClaim)...)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newClaim, oldClaim, errs, operation.Update)
return errs
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -25,6 +25,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -36,7 +37,7 @@ import (
// resourceClaimTemplateStrategy implements behavior for ResourceClaimTemplate objects
type resourceClaimTemplateStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
nsClient v1.NamespaceInterface
}
@ -44,7 +45,7 @@ type resourceClaimTemplateStrategy struct {
// NewStrategy is the default logic that applies when creating and updating ResourceClaimTemplate objects.
func NewStrategy(nsClient v1.NamespaceInterface) *resourceClaimTemplateStrategy {
return &resourceClaimTemplateStrategy{
legacyscheme.Scheme,
rest.DeclarativeValidation{Scheme: legacyscheme.Scheme},
names.SimpleNameGenerator,
nsClient,
}

View file

@ -92,7 +92,7 @@ func TestDeclarativeValidate(t *testing.T) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs)
})
}
}
@ -129,7 +129,7 @@ func TestDeclarativeValidateUpdate(t *testing.T) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, Strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, Strategy, tc.expectedErrs)
})
}
}
@ -341,7 +341,7 @@ func TestDeclarativeValidateStatusUpdate(t *testing.T) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, StatusStrategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, StatusStrategy, tc.expectedErrs)
})
}
}

View file

@ -19,7 +19,6 @@ package resourcepoolstatusrequest
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
@ -33,12 +32,12 @@ import (
// resourcePoolStatusRequestStrategy implements behavior for ResourcePoolStatusRequest objects
type resourcePoolStatusRequestStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
var (
Strategy = &resourcePoolStatusRequestStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
Strategy = &resourcePoolStatusRequestStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
StatusStrategy = &resourcePoolStatusRequestStatusStrategy{resourcePoolStatusRequestStrategy: Strategy}
)
@ -67,8 +66,13 @@ func (*resourcePoolStatusRequestStrategy) PrepareForCreate(ctx context.Context,
func (*resourcePoolStatusRequestStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
request := obj.(*resource.ResourcePoolStatusRequest)
allErrs := validation.ValidateResourcePoolStatusRequest(request)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, nil, allErrs, operation.Create, rest.WithDeclarativeEnforcement())
return validation.ValidateResourcePoolStatusRequest(request)
}
// DeclarativeValidationConfig implements rest.DeclarativeValidationConfigurer to supply declarative
// validation options to the generic BeforeCreate/BeforeUpdate code path.
func (*resourcePoolStatusRequestStrategy) DeclarativeValidationConfig(ctx context.Context, obj, oldObj runtime.Object) rest.DeclarativeValidationConfig {
return rest.DeclarativeValidationConfig{DeclarativeEnforcement: true}
}
func (*resourcePoolStatusRequestStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
@ -90,8 +94,7 @@ func (*resourcePoolStatusRequestStrategy) PrepareForUpdate(ctx context.Context,
}
func (*resourcePoolStatusRequestStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
allErrs := validation.ValidateResourcePoolStatusRequestUpdate(obj.(*resource.ResourcePoolStatusRequest), old.(*resource.ResourcePoolStatusRequest))
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, old, allErrs, operation.Update, rest.WithDeclarativeEnforcement())
return validation.ValidateResourcePoolStatusRequestUpdate(obj.(*resource.ResourcePoolStatusRequest), old.(*resource.ResourcePoolStatusRequest))
}
func (*resourcePoolStatusRequestStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
@ -129,8 +132,7 @@ func (*resourcePoolStatusRequestStatusStrategy) PrepareForUpdate(ctx context.Con
func (r *resourcePoolStatusRequestStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
newRequest := obj.(*resource.ResourcePoolStatusRequest)
oldRequest := old.(*resource.ResourcePoolStatusRequest)
allErrs := validation.ValidateResourcePoolStatusRequestStatusUpdate(newRequest, oldRequest)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, old, allErrs, operation.Update, rest.WithDeclarativeEnforcement())
return validation.ValidateResourcePoolStatusRequestStatusUpdate(newRequest, oldRequest)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -240,7 +240,7 @@ func TestDeclarativeValidate(t *testing.T) {
for k, tc := range testCases {
t.Run(k, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(
t, ctx, &tc.input, strategy.Validate, tc.expectedErrs,
t, ctx, &tc.input, strategy, tc.expectedErrs,
apitesting.WithNormalizationRules(validation.ResourceNormalizationRules...),
apitesting.WithIgnoreObjectConversionErrors(),
)
@ -459,7 +459,7 @@ func TestDeclarativeValidateUpdate(t *testing.T) {
t.Run(k, func(t *testing.T) {
tc.old.ResourceVersion = "1"
tc.update.ResourceVersion = "1"
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, strategy.ValidateUpdate, tc.expectedErrs, apitesting.WithNormalizationRules(validation.ResourceNormalizationRules...))
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.update, &tc.old, strategy, tc.expectedErrs, apitesting.WithNormalizationRules(validation.ResourceNormalizationRules...))
})
}
})

View file

@ -22,7 +22,6 @@ import (
"strings"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
@ -41,11 +40,11 @@ import (
// resourceSliceStrategy implements behavior for ResourceSlice objects
type resourceSliceStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
var Strategy = resourceSliceStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = resourceSliceStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (resourceSliceStrategy) NamespaceScoped() bool {
return false
@ -60,9 +59,13 @@ func (resourceSliceStrategy) PrepareForCreate(ctx context.Context, obj runtime.O
func (resourceSliceStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
slice := obj.(*resource.ResourceSlice)
errorList := validation.ValidateResourceSlice(slice)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, slice, nil, errorList, operation.Create, rest.WithNormalizationRules(validation.ResourceNormalizationRules))
return validation.ValidateResourceSlice(slice)
}
// DeclarativeValidationConfig implements rest.DeclarativeValidationConfigurer to supply declarative
// validation options to the generic BeforeCreate/BeforeUpdate code path.
func (resourceSliceStrategy) DeclarativeValidationConfig(ctx context.Context, obj, oldObj runtime.Object) rest.DeclarativeValidationConfig {
return rest.DeclarativeValidationConfig{NormalizationRules: validation.ResourceNormalizationRules}
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -98,8 +101,7 @@ func (resourceSliceStrategy) PrepareForUpdate(ctx context.Context, obj, old runt
}
func (resourceSliceStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
errorList := validation.ValidateResourceSliceUpdate(obj.(*resource.ResourceSlice), old.(*resource.ResourceSlice))
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, old, errorList, operation.Update, rest.WithNormalizationRules(validation.ResourceNormalizationRules))
return validation.ValidateResourceSliceUpdate(obj.(*resource.ResourceSlice), old.(*resource.ResourceSlice))
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -341,7 +341,7 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
features.GangScheduling: tc.enableWorkloadAwarePreemption,
features.WorkloadAwarePreemption: tc.enableWorkloadAwarePreemption,
})
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, strategy.Validate, tc.expectedErrs, apitesting.WithMinEmulationVersion(version.MustParse("1.36")))
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, strategy, tc.expectedErrs, apitesting.WithMinEmulationVersion(version.MustParse("1.36")))
})
}
}
@ -566,7 +566,7 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
features.WorkloadAwarePreemption: tc.enableWorkloadAwarePreemption,
})
strategy := NewStrategy()
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, strategy.ValidateUpdate, tc.expectedErrs, apitesting.WithMinEmulationVersion(version.MustParse("1.36")))
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, strategy, tc.expectedErrs, apitesting.WithMinEmulationVersion(version.MustParse("1.36")))
})
}
}
@ -689,7 +689,7 @@ func testDeclarativeValidateStatusUpdate(t *testing.T, apiVersion string) {
for k, tc := range testCases {
t.Run(k, func(t *testing.T) {
strategy := NewStatusStrategy(NewStrategy())
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, strategy, tc.expectedErrs)
})
}
}

View file

@ -21,7 +21,6 @@ import (
"sigs.k8s.io/structured-merge-diff/v6/fieldpath"
"k8s.io/apimachinery/pkg/api/operation"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
@ -36,14 +35,14 @@ import (
// podGroupStrategy implements behavior for PodGroup objects.
type podGroupStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// NewStrategy is the default logic that applies when creating and updating PodGroup objects.
func NewStrategy() *podGroupStrategy {
return &podGroupStrategy{
legacyscheme.Scheme,
rest.DeclarativeValidation{Scheme: legacyscheme.Scheme},
names.SimpleNameGenerator,
}
}
@ -73,7 +72,21 @@ func (*podGroupStrategy) PrepareForCreate(ctx context.Context, obj runtime.Objec
func (*podGroupStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
podGroup := obj.(*scheduling.PodGroup)
allErrs := validation.ValidatePodGroup(podGroup)
return validation.ValidatePodGroup(podGroup)
}
// DeclarativeValidationConfig implements rest.DeclarativeValidationConfigurer to supply declarative
// validation options to the generic BeforeCreate/BeforeUpdate code path.
//
// TODO: Behavior drift introduced when wiring declarative validation
// universally: the status substrategy embeds *podGroupStrategy and now
// inherits this method, so status updates pick up the full feature-gated
// options list and rest.WithDeclarativeEnforcement(). Previously the
// pre-migration inline call on the status subresource only passed
// WithDeclarativeEnforcement() (no options list). The change is additive but
// should be reviewed; if the status subresource should not see these
// options, override ValidationConfig on podGroupStatusStrategy.
func (*podGroupStrategy) DeclarativeValidationConfig(ctx context.Context, obj, oldObj runtime.Object) rest.DeclarativeValidationConfig {
opts := []string{}
if utilfeature.DefaultFeatureGate.Enabled(features.TopologyAwareWorkloadScheduling) {
opts = append(opts, string(features.TopologyAwareWorkloadScheduling))
@ -84,7 +97,7 @@ func (*podGroupStrategy) Validate(ctx context.Context, obj runtime.Object) field
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) {
opts = append(opts, string(features.WorkloadAwarePreemption))
}
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, nil, allErrs, operation.Create, rest.WithDeclarativeEnforcement(), rest.WithOptions(opts))
return rest.DeclarativeValidationConfig{DeclarativeEnforcement: true, Options: opts}
}
func (*podGroupStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
@ -107,22 +120,7 @@ func (*podGroupStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
func (*podGroupStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
newPodGroup := obj.(*scheduling.PodGroup)
oldPodGroup := old.(*scheduling.PodGroup)
allErrs := validation.ValidatePodGroupUpdate(newPodGroup, oldPodGroup)
opts := []string{}
// Declarative validation will always allow fields to remain unchanged, so if any
// of the fields which are covered by these gates are set, we will not re-validate them
// (even if the gates are disabled) as long as they do not change values. If a gate
// is disabled, they will not be allowed to change values.
if utilfeature.DefaultFeatureGate.Enabled(features.TopologyAwareWorkloadScheduling) {
opts = append(opts, string(features.TopologyAwareWorkloadScheduling))
}
if utilfeature.DefaultFeatureGate.Enabled(features.DRAWorkloadResourceClaims) {
opts = append(opts, string(features.DRAWorkloadResourceClaims))
}
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) {
opts = append(opts, string(features.WorkloadAwarePreemption))
}
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newPodGroup, oldPodGroup, allErrs, operation.Update, rest.WithDeclarativeEnforcement(), rest.WithOptions(opts))
return validation.ValidatePodGroupUpdate(newPodGroup, oldPodGroup)
}
func (*podGroupStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
@ -166,8 +164,7 @@ func (*podGroupStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old ru
func (r *podGroupStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
newPodGroup := obj.(*scheduling.PodGroup)
oldPodGroup := old.(*scheduling.PodGroup)
errs := validation.ValidatePodGroupStatusUpdate(newPodGroup, oldPodGroup)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, newPodGroup, oldPodGroup, errs, operation.Update, rest.WithDeclarativeEnforcement())
return validation.ValidatePodGroupStatusUpdate(newPodGroup, oldPodGroup)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -21,6 +21,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/scheduling"
@ -29,12 +30,12 @@ import (
// priorityClassStrategy implements verification logic for PriorityClass.
type priorityClassStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating PriorityClass objects.
var Strategy = priorityClassStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = priorityClassStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
// NamespaceScoped returns false because all PriorityClasses are global.
func (priorityClassStrategy) NamespaceScoped() bool {

View file

@ -359,7 +359,7 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
features.GangScheduling: tc.enableWorkloadAwarePreemption,
features.WorkloadAwarePreemption: tc.enableWorkloadAwarePreemption,
})
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs, apitesting.WithMinEmulationVersion(version.MustParse("1.36")))
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs, apitesting.WithMinEmulationVersion(version.MustParse("1.36")))
})
}
}
@ -605,7 +605,7 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
IsResourceRequest: true,
Verb: "update",
})
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, Strategy.ValidateUpdate, tc.expectedErrs, apitesting.WithMinEmulationVersion(version.MustParse("1.36")))
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, Strategy, tc.expectedErrs, apitesting.WithMinEmulationVersion(version.MustParse("1.36")))
})
}
}

View file

@ -19,7 +19,6 @@ package workload
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
@ -33,12 +32,12 @@ import (
// workloadStrategy implements behavior for Workload objects.
type workloadStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating Workload objects.
var Strategy = workloadStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = workloadStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (workloadStrategy) NamespaceScoped() bool {
return true
@ -50,7 +49,12 @@ func (workloadStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object
func (workloadStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
workloadScheduling := obj.(*scheduling.Workload)
allErrs := validation.ValidateWorkload(workloadScheduling)
return validation.ValidateWorkload(workloadScheduling)
}
// DeclarativeValidationConfig implements rest.DeclarativeValidationConfigurer to supply declarative
// validation options to the generic BeforeCreate/BeforeUpdate code path.
func (workloadStrategy) DeclarativeValidationConfig(ctx context.Context, obj, oldObj runtime.Object) rest.DeclarativeValidationConfig {
opts := []string{}
if utilfeature.DefaultFeatureGate.Enabled(features.TopologyAwareWorkloadScheduling) {
opts = append(opts, string(features.TopologyAwareWorkloadScheduling))
@ -61,7 +65,7 @@ func (workloadStrategy) Validate(ctx context.Context, obj runtime.Object) field.
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) {
opts = append(opts, string(features.WorkloadAwarePreemption))
}
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, nil, allErrs, operation.Create, rest.WithDeclarativeEnforcement(), rest.WithOptions(opts))
return rest.DeclarativeValidationConfig{DeclarativeEnforcement: true, Options: opts}
}
func (workloadStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
@ -79,22 +83,7 @@ func (workloadStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.O
}
func (workloadStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
allErrs := validation.ValidateWorkloadUpdate(obj.(*scheduling.Workload), old.(*scheduling.Workload))
opts := []string{}
// Declarative validation will always allow fields to remain unchanged, so if any
// of the fields which are covered by these gates are set, we will not re-validate them
// (even if the gates are disabled) as long as they do not change values. If a gate
// is disabled, they will not be allowed to change values.
if utilfeature.DefaultFeatureGate.Enabled(features.TopologyAwareWorkloadScheduling) {
opts = append(opts, string(features.TopologyAwareWorkloadScheduling))
}
if utilfeature.DefaultFeatureGate.Enabled(features.DRAWorkloadResourceClaims) {
opts = append(opts, string(features.DRAWorkloadResourceClaims))
}
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) {
opts = append(opts, string(features.WorkloadAwarePreemption))
}
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, old, allErrs, operation.Update, rest.WithDeclarativeEnforcement(), rest.WithOptions(opts))
return validation.ValidateWorkloadUpdate(obj.(*scheduling.Workload), old.(*scheduling.Workload))
}
func (workloadStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {

View file

@ -22,6 +22,7 @@ import (
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -36,13 +37,13 @@ const (
// csiDriverStrategy implements behavior for CSIDriver objects
type csiDriverStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// CSIDriver objects via the REST API.
var Strategy = csiDriverStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = csiDriverStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (csiDriverStrategy) NamespaceScoped() bool {
return false

View file

@ -21,6 +21,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/storage"
@ -29,13 +30,13 @@ import (
// csiNodeStrategy implements behavior for CSINode objects
type csiNodeStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// CSINode objects via the REST API.
var Strategy = csiNodeStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = csiNodeStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (csiNodeStrategy) NamespaceScoped() bool {
return false

View file

@ -22,6 +22,7 @@ import (
metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
storageutil "k8s.io/kubernetes/pkg/api/storage"
@ -31,13 +32,13 @@ import (
// csiStorageCapacityStrategy implements behavior for CSIStorageCapacity objects
type csiStorageCapacityStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// CSIStorageCapacity objects via the REST API.
var Strategy = csiStorageCapacityStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = csiStorageCapacityStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (csiStorageCapacityStrategy) NamespaceScoped() bool {
return true

View file

@ -65,7 +65,7 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
}
for k, tc := range testCases {
t.Run(k, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs)
})
}
}
@ -188,7 +188,7 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
IsResourceRequest: true,
Verb: "update",
})
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, Strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, Strategy, tc.expectedErrs)
})
}
}

View file

@ -18,7 +18,7 @@ package storageclass
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apimachinery/pkg/runtime"
@ -32,13 +32,13 @@ import (
// storageClassStrategy implements behavior for StorageClass objects
type storageClassStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// StorageClass objects via the REST API.
var Strategy = storageClassStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = storageClassStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (storageClassStrategy) NamespaceScoped() bool {
return false
@ -50,8 +50,7 @@ func (storageClassStrategy) PrepareForCreate(ctx context.Context, obj runtime.Ob
func (storageClassStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
storageClass := obj.(*storage.StorageClass)
allErrs := validation.ValidateStorageClass(storageClass)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, nil, allErrs, operation.Create)
return validation.ValidateStorageClass(storageClass)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -74,7 +73,7 @@ func (storageClassStrategy) PrepareForUpdate(ctx context.Context, obj, old runti
func (storageClassStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
allErrs := validation.ValidateStorageClass(obj.(*storage.StorageClass))
allErrs = append(allErrs, validation.ValidateStorageClassUpdate(obj.(*storage.StorageClass), old.(*storage.StorageClass))...)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, old, allErrs, operation.Update)
return allErrs
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -89,7 +89,7 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy.Validate, tc.expectedErrs)
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, Strategy, tc.expectedErrs)
})
}
}
@ -123,7 +123,7 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.newInput, &tc.oldInput, Strategy.ValidateUpdate, tc.expectedErrs)
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.newInput, &tc.oldInput, Strategy, tc.expectedErrs)
})
}
}

View file

@ -18,7 +18,7 @@ package volumeattachment
import (
"context"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apiserver/pkg/registry/rest"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -35,13 +35,13 @@ import (
// volumeAttachmentStrategy implements behavior for VolumeAttachment objects
type volumeAttachmentStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// VolumeAttachment objects via the REST API.
var Strategy = volumeAttachmentStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = volumeAttachmentStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (volumeAttachmentStrategy) NamespaceScoped() bool {
return false
@ -67,8 +67,7 @@ func (volumeAttachmentStrategy) PrepareForCreate(ctx context.Context, obj runtim
func (volumeAttachmentStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
volumeAttachment := obj.(*storage.VolumeAttachment)
errs := validation.ValidateVolumeAttachment(volumeAttachment)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, nil, errs, operation.Create)
return validation.ValidateVolumeAttachment(volumeAttachment)
}
// WarningsOnCreate returns warnings for the creation of the given object.
@ -97,8 +96,7 @@ func (volumeAttachmentStrategy) PrepareForUpdate(ctx context.Context, obj, old r
func (volumeAttachmentStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
newVolumeAttachmentObj := obj.(*storage.VolumeAttachment)
oldVolumeAttachmentObj := old.(*storage.VolumeAttachment)
allErrs := validation.ValidateVolumeAttachmentUpdate(newVolumeAttachmentObj, oldVolumeAttachmentObj)
return rest.ValidateDeclarativelyWithMigrationChecks(ctx, legacyscheme.Scheme, obj, old, allErrs, operation.Update)
return validation.ValidateVolumeAttachmentUpdate(newVolumeAttachmentObj, oldVolumeAttachmentObj)
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -21,6 +21,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/storage"
@ -29,13 +30,13 @@ import (
// volumeAttributesClassStrategy implements behavior for VolumeAttributesClassStrategy objects
type volumeAttributesClassStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// VolumeAttributesClass objects via the REST API.
var Strategy = volumeAttributesClassStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = volumeAttributesClassStrategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
func (volumeAttributesClassStrategy) NamespaceScoped() bool {
return false

View file

@ -35,12 +35,12 @@ import (
// strategy implements behavior for ClusterTrustBundles.
type strategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
}
// Strategy is the create, update, and delete strategy for ClusterTrustBundles.
var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator}
var Strategy = strategy{rest.DeclarativeValidation{Scheme: legacyscheme.Scheme}, names.SimpleNameGenerator}
var _ rest.RESTCreateStrategy = Strategy
var _ rest.RESTUpdateStrategy = Strategy

View file

@ -27,6 +27,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/names"
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
@ -36,7 +37,7 @@ import (
// carpStrategy implements behavior for Carp objects
type carpStrategy struct {
runtime.ObjectTyper
rest.DeclarativeValidation
names.NameGenerator
nsClient v1.NamespaceInterface
}
@ -44,7 +45,7 @@ type carpStrategy struct {
// NewStrategy is the default logic that applies when creating and updating Carp objects.
func NewStrategy(nsClient v1.NamespaceInterface) *carpStrategy {
return &carpStrategy{
legacyscheme.Scheme,
rest.DeclarativeValidation{Scheme: legacyscheme.Scheme},
names.SimpleNameGenerator,
nsClient,
}