From 015b89788b1480cdf2ca74de33f8fd8b82a21bb9 Mon Sep 17 00:00:00 2001 From: Joe Betz Date: Fri, 10 Apr 2026 15:59:25 -0400 Subject: [PATCH] Test that all strategies opt-in to declarative validation --- pkg/controlplane/instance_test.go | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/pkg/controlplane/instance_test.go b/pkg/controlplane/instance_test.go index 120642eeae2..6c2075bf405 100644 --- a/pkg/controlplane/instance_test.go +++ b/pkg/controlplane/instance_test.go @@ -49,6 +49,7 @@ import ( "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizerfactory" openapinamer "k8s.io/apiserver/pkg/endpoints/openapi" + "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" genericapiserver "k8s.io/apiserver/pkg/server" "k8s.io/apiserver/pkg/server/options" @@ -651,6 +652,59 @@ func TestGetResetFieldsHasAllVersions(t *testing.T) { } } +// TestDeclarativeValidationEnablementInStrategies verifies that every CreateStrategy and +// UpdateStrategy installed supports declarative validation. +func TestDeclarativeValidationEnablementInStrategies(t *testing.T) { + _, config, _ := setUp(t) + + client, err := kubernetes.NewForConfig(config.ControlPlane.Generic.LoopbackClientConfig) + if err != nil { + t.Fatal(err) + } + + providers, err := config.Complete().StorageProviders(client) + if err != nil { + t.Fatal(err) + } + + // Enable all versions (including alpha and beta) so the check covers + // every resource that kube-apiserver can serve. + allVersionsConfig := DefaultAPIResourceConfigSource() + allVersionsConfig.EnableVersions(betaAPIGroupVersionsDisabledByDefault...) + allVersionsConfig.EnableVersions(alphaAPIGroupVersionsDisabledByDefault...) + + for _, provider := range providers { + groupName := provider.GroupName() + apiGroupInfo, err := provider.NewRESTStorage(allVersionsConfig, config.ControlPlane.Generic.RESTOptionsGetter) + if err != nil { + t.Errorf("error creating REST storage for %s: %v", groupName, err) + continue + } + + for v, resourcesInVersion := range apiGroupInfo.VersionedResourcesStorageMap { + for resource, storage := range resourcesInVersion { + gs, ok := storage.(registry.GenericStore) + if !ok { + // Non-generic storage (e.g. proxy/exec subresources) + // has no strategy to check. + continue + } + name := gvr(groupName, v, resource) + if cs := gs.GetCreateStrategy(); cs != nil { + if _, ok := cs.(rest.DeclarativeValidationStrategy); !ok { + t.Errorf("%s: CreateStrategy %T does not implement rest.DeclarativeValidationStrategy; embed rest.DeclarativeValidation to enable automatic declarative validation", name, cs) + } + } + if us := gs.GetUpdateStrategy(); us != nil { + if _, ok := us.(rest.DeclarativeValidationStrategy); !ok { + t.Errorf("%s: UpdateStrategy %T does not implement rest.DeclarativeValidationStrategy; embed rest.DeclarativeValidation to enable automatic declarative validation", name, us) + } + } + } + } + } +} + func gvr(g string, v string, r string) string { var gvr string if len(g) == 0 {