diff --git a/pkg/registry/admissionregistration/mutatingwebhookconfiguration/storage/storage.go b/pkg/registry/admissionregistration/mutatingwebhookconfiguration/storage/storage.go index 54207b62423..75c92690f1f 100644 --- a/pkg/registry/admissionregistration/mutatingwebhookconfiguration/storage/storage.go +++ b/pkg/registry/admissionregistration/mutatingwebhookconfiguration/storage/storage.go @@ -41,7 +41,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*admissionregistration.MutatingWebhookConfiguration).Name, nil }, - DefaultQualifiedResource: admissionregistration.Resource("mutatingwebhookconfigurations"), + DefaultQualifiedResource: admissionregistration.Resource("mutatingwebhookconfigurations"), + SingularQualifiedResource: admissionregistration.Resource("mutatingwebhookconfiguration"), CreateStrategy: mutatingwebhookconfiguration.Strategy, UpdateStrategy: mutatingwebhookconfiguration.Strategy, diff --git a/pkg/registry/admissionregistration/validatingwebhookconfiguration/storage/storage.go b/pkg/registry/admissionregistration/validatingwebhookconfiguration/storage/storage.go index 507c0d9e758..6312f6a0cd0 100644 --- a/pkg/registry/admissionregistration/validatingwebhookconfiguration/storage/storage.go +++ b/pkg/registry/admissionregistration/validatingwebhookconfiguration/storage/storage.go @@ -41,7 +41,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*admissionregistration.ValidatingWebhookConfiguration).Name, nil }, - DefaultQualifiedResource: admissionregistration.Resource("validatingwebhookconfigurations"), + DefaultQualifiedResource: admissionregistration.Resource("validatingwebhookconfigurations"), + SingularQualifiedResource: admissionregistration.Resource("validatingwebhookconfiguration"), CreateStrategy: validatingwebhookconfiguration.Strategy, UpdateStrategy: validatingwebhookconfiguration.Strategy, diff --git a/pkg/registry/apiserverinternal/storageversion/storage/storage.go b/pkg/registry/apiserverinternal/storageversion/storage/storage.go index 7bb55c31ed8..f4cf8bbec3d 100644 --- a/pkg/registry/apiserverinternal/storageversion/storage/storage.go +++ b/pkg/registry/apiserverinternal/storageversion/storage/storage.go @@ -45,7 +45,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*apiserverinternal.StorageVersion).Name, nil }, - DefaultQualifiedResource: apiserverinternal.Resource("storageversions"), + DefaultQualifiedResource: apiserverinternal.Resource("storageversions"), + SingularQualifiedResource: apiserverinternal.Resource("storageversion"), CreateStrategy: strategy.Strategy, UpdateStrategy: strategy.Strategy, @@ -99,3 +100,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/apps/controllerrevision/storage/storage.go b/pkg/registry/apps/controllerrevision/storage/storage.go index f00f1b80992..c4f9179aa22 100644 --- a/pkg/registry/apps/controllerrevision/storage/storage.go +++ b/pkg/registry/apps/controllerrevision/storage/storage.go @@ -35,9 +35,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work with ControllerRevision objects. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &apps.ControllerRevision{} }, - NewListFunc: func() runtime.Object { return &apps.ControllerRevisionList{} }, - DefaultQualifiedResource: apps.Resource("controllerrevisions"), + NewFunc: func() runtime.Object { return &apps.ControllerRevision{} }, + NewListFunc: func() runtime.Object { return &apps.ControllerRevisionList{} }, + DefaultQualifiedResource: apps.Resource("controllerrevisions"), + SingularQualifiedResource: apps.Resource("controllerrevision"), CreateStrategy: controllerrevision.Strategy, UpdateStrategy: controllerrevision.Strategy, diff --git a/pkg/registry/apps/daemonset/storage/storage.go b/pkg/registry/apps/daemonset/storage/storage.go index c40ac6fc36d..b2541039713 100644 --- a/pkg/registry/apps/daemonset/storage/storage.go +++ b/pkg/registry/apps/daemonset/storage/storage.go @@ -40,9 +40,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against DaemonSets. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &apps.DaemonSet{} }, - NewListFunc: func() runtime.Object { return &apps.DaemonSetList{} }, - DefaultQualifiedResource: apps.Resource("daemonsets"), + NewFunc: func() runtime.Object { return &apps.DaemonSet{} }, + NewListFunc: func() runtime.Object { return &apps.DaemonSetList{} }, + DefaultQualifiedResource: apps.Resource("daemonsets"), + SingularQualifiedResource: apps.Resource("daemonset"), CreateStrategy: daemonset.Strategy, UpdateStrategy: daemonset.Strategy, @@ -78,13 +79,6 @@ func (r *REST) Categories() []string { return []string{"all"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "daemonset" -} - // StatusREST implements the REST endpoint for changing the status of a daemonset type StatusREST struct { store *genericregistry.Store @@ -121,3 +115,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/apps/daemonset/storage/storage_test.go b/pkg/registry/apps/daemonset/storage/storage_test.go index fcd06c180dd..eaf15ffcdae 100644 --- a/pkg/registry/apps/daemonset/storage/storage_test.go +++ b/pkg/registry/apps/daemonset/storage/storage_test.go @@ -197,12 +197,4 @@ func TestShortNames(t *testing.T) { registrytest.AssertShortNames(t, storage, expected) } -func TestSingularName(t *testing.T) { - storage, _, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "daemonset" - registrytest.AssertSingularName(t, storage, expected) -} - // TODO TestUpdateStatus diff --git a/pkg/registry/apps/deployment/storage/storage.go b/pkg/registry/apps/deployment/storage/storage.go index 3da212d0974..c94f5da9198 100644 --- a/pkg/registry/apps/deployment/storage/storage.go +++ b/pkg/registry/apps/deployment/storage/storage.go @@ -92,9 +92,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against deployments. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *RollbackREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &apps.Deployment{} }, - NewListFunc: func() runtime.Object { return &apps.DeploymentList{} }, - DefaultQualifiedResource: apps.Resource("deployments"), + NewFunc: func() runtime.Object { return &apps.Deployment{} }, + NewListFunc: func() runtime.Object { return &apps.DeploymentList{} }, + DefaultQualifiedResource: apps.Resource("deployments"), + SingularQualifiedResource: apps.Resource("deployment"), CreateStrategy: deployment.Strategy, UpdateStrategy: deployment.Strategy, @@ -130,13 +131,6 @@ func (r *REST) Categories() []string { return []string{"all"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "deployment" -} - // StatusREST implements the REST endpoint for changing the status of a deployment type StatusREST struct { store *genericregistry.Store @@ -174,6 +168,12 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, return r.store.ConvertToTable(ctx, object, tableOptions) } +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} + // RollbackREST implements the REST endpoint for initiating the rollback of a deployment type RollbackREST struct { store *genericregistry.Store @@ -204,6 +204,12 @@ func (r *RollbackREST) Destroy() { // we don't destroy it here explicitly. } +var _ rest.SingularNameProvider = &RollbackREST{} + +func (r *RollbackREST) GetSingularName() string { + return r.store.GetSingularName() +} + var _ = rest.NamedCreater(&RollbackREST{}) // Create runs rollback for deployment @@ -348,6 +354,12 @@ func (r *ScaleREST) ConvertToTable(ctx context.Context, object runtime.Object, t return r.store.ConvertToTable(ctx, object, tableOptions) } +var _ rest.SingularNameProvider = &ScaleREST{} + +func (r *ScaleREST) GetSingularName() string { + return r.store.GetSingularName() +} + func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc { return func(ctx context.Context, obj runtime.Object) error { scale, err := scaleFromDeployment(obj.(*apps.Deployment)) diff --git a/pkg/registry/apps/deployment/storage/storage_test.go b/pkg/registry/apps/deployment/storage/storage_test.go index 05b14b0b45e..d7b371040d2 100644 --- a/pkg/registry/apps/deployment/storage/storage_test.go +++ b/pkg/registry/apps/deployment/storage/storage_test.go @@ -455,14 +455,6 @@ func TestCategories(t *testing.T) { registrytest.AssertCategories(t, storage.Deployment, expected) } -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Deployment.Store.DestroyFunc() - expected := "deployment" - registrytest.AssertSingularName(t, storage.Deployment, expected) -} - func TestScalePatchErrors(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) diff --git a/pkg/registry/apps/replicaset/storage/storage.go b/pkg/registry/apps/replicaset/storage/storage.go index 97592c1d770..b0d44428bb7 100644 --- a/pkg/registry/apps/replicaset/storage/storage.go +++ b/pkg/registry/apps/replicaset/storage/storage.go @@ -86,10 +86,11 @@ type REST struct { // NewREST returns a RESTStorage object that will work against ReplicaSet. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &apps.ReplicaSet{} }, - NewListFunc: func() runtime.Object { return &apps.ReplicaSetList{} }, - PredicateFunc: replicaset.MatchReplicaSet, - DefaultQualifiedResource: apps.Resource("replicasets"), + NewFunc: func() runtime.Object { return &apps.ReplicaSet{} }, + NewListFunc: func() runtime.Object { return &apps.ReplicaSetList{} }, + PredicateFunc: replicaset.MatchReplicaSet, + DefaultQualifiedResource: apps.Resource("replicasets"), + SingularQualifiedResource: apps.Resource("replicaset"), CreateStrategy: replicaset.Strategy, UpdateStrategy: replicaset.Strategy, @@ -126,13 +127,6 @@ func (r *REST) Categories() []string { return []string{"all"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "replicaset" -} - // StatusREST implements the REST endpoint for changing the status of a ReplicaSet type StatusREST struct { store *genericregistry.Store @@ -170,6 +164,12 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, return r.store.ConvertToTable(ctx, object, tableOptions) } +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} + // ScaleREST implements a Scale for ReplicaSet. type ScaleREST struct { store *genericregistry.Store @@ -244,6 +244,12 @@ func (r *ScaleREST) ConvertToTable(ctx context.Context, object runtime.Object, t return r.store.ConvertToTable(ctx, object, tableOptions) } +var _ rest.SingularNameProvider = &ScaleREST{} + +func (r *ScaleREST) GetSingularName() string { + return r.store.GetSingularName() +} + func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc { return func(ctx context.Context, obj runtime.Object) error { scale, err := scaleFromReplicaSet(obj.(*apps.ReplicaSet)) diff --git a/pkg/registry/apps/replicaset/storage/storage_test.go b/pkg/registry/apps/replicaset/storage/storage_test.go index d6223bbe849..392c1f95b21 100644 --- a/pkg/registry/apps/replicaset/storage/storage_test.go +++ b/pkg/registry/apps/replicaset/storage/storage_test.go @@ -399,14 +399,6 @@ func TestCategories(t *testing.T) { registrytest.AssertCategories(t, storage.ReplicaSet, expected) } -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.ReplicaSet.Store.DestroyFunc() - expected := "replicaset" - registrytest.AssertSingularName(t, storage.ReplicaSet, expected) -} - func TestScalePatchErrors(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) diff --git a/pkg/registry/apps/statefulset/storage/storage.go b/pkg/registry/apps/statefulset/storage/storage.go index cf834362f9f..b98ce47d7fa 100644 --- a/pkg/registry/apps/statefulset/storage/storage.go +++ b/pkg/registry/apps/statefulset/storage/storage.go @@ -84,9 +84,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against statefulsets. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &apps.StatefulSet{} }, - NewListFunc: func() runtime.Object { return &apps.StatefulSetList{} }, - DefaultQualifiedResource: apps.Resource("statefulsets"), + NewFunc: func() runtime.Object { return &apps.StatefulSet{} }, + NewListFunc: func() runtime.Object { return &apps.StatefulSetList{} }, + DefaultQualifiedResource: apps.Resource("statefulsets"), + SingularQualifiedResource: apps.Resource("statefulset"), CreateStrategy: statefulset.Strategy, UpdateStrategy: statefulset.Strategy, @@ -114,13 +115,6 @@ func (r *REST) Categories() []string { return []string{"all"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "statefulset" -} - // StatusREST implements the REST endpoint for changing the status of an statefulSet type StatusREST struct { store *genericregistry.Store @@ -158,6 +152,12 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, return r.store.ConvertToTable(ctx, object, tableOptions) } +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} + // Implement ShortNamesProvider var _ rest.ShortNamesProvider = &REST{} @@ -238,6 +238,12 @@ func (r *ScaleREST) ConvertToTable(ctx context.Context, object runtime.Object, t return r.store.ConvertToTable(ctx, object, tableOptions) } +var _ rest.SingularNameProvider = &ScaleREST{} + +func (r *ScaleREST) GetSingularName() string { + return r.store.GetSingularName() +} + func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc { return func(ctx context.Context, obj runtime.Object) error { scale, err := scaleFromStatefulSet(obj.(*apps.StatefulSet)) diff --git a/pkg/registry/apps/statefulset/storage/storage_test.go b/pkg/registry/apps/statefulset/storage/storage_test.go index 649ffffed15..cdce909bd77 100644 --- a/pkg/registry/apps/statefulset/storage/storage_test.go +++ b/pkg/registry/apps/statefulset/storage/storage_test.go @@ -199,14 +199,6 @@ func TestCategories(t *testing.T) { registrytest.AssertCategories(t, storage.StatefulSet, expected) } -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.StatefulSet.Store.DestroyFunc() - expected := "statefulset" - registrytest.AssertSingularName(t, storage.StatefulSet, expected) -} - func TestShortNames(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) diff --git a/pkg/registry/authentication/tokenreview/storage.go b/pkg/registry/authentication/tokenreview/storage.go index 46f3e00f1ac..1c9c328603f 100644 --- a/pkg/registry/authentication/tokenreview/storage.go +++ b/pkg/registry/authentication/tokenreview/storage.go @@ -60,6 +60,12 @@ func (r *REST) Destroy() { // here explicitly. } +var _ rest.SingularNameProvider = &REST{} + +func (r *REST) GetSingularName() string { + return "tokenreview" +} + func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { tokenReview, ok := obj.(*authentication.TokenReview) if !ok { diff --git a/pkg/registry/authorization/localsubjectaccessreview/rest.go b/pkg/registry/authorization/localsubjectaccessreview/rest.go index e28b03dc368..78389075064 100644 --- a/pkg/registry/authorization/localsubjectaccessreview/rest.go +++ b/pkg/registry/authorization/localsubjectaccessreview/rest.go @@ -53,6 +53,12 @@ func (r *REST) Destroy() { // here explicitly. } +var _ rest.SingularNameProvider = &REST{} + +func (r *REST) GetSingularName() string { + return "localsubjectaccessreview" +} + func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { localSubjectAccessReview, ok := obj.(*authorizationapi.LocalSubjectAccessReview) if !ok { diff --git a/pkg/registry/authorization/selfsubjectaccessreview/rest.go b/pkg/registry/authorization/selfsubjectaccessreview/rest.go index f2c3a9a0b3c..f5e6be5227a 100644 --- a/pkg/registry/authorization/selfsubjectaccessreview/rest.go +++ b/pkg/registry/authorization/selfsubjectaccessreview/rest.go @@ -53,6 +53,12 @@ func (r *REST) Destroy() { // here explicitly. } +var _ rest.SingularNameProvider = &REST{} + +func (r *REST) GetSingularName() string { + return "selfsubjectaccessreview" +} + func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { selfSAR, ok := obj.(*authorizationapi.SelfSubjectAccessReview) if !ok { diff --git a/pkg/registry/authorization/selfsubjectrulesreview/rest.go b/pkg/registry/authorization/selfsubjectrulesreview/rest.go index f1c3a9f86c7..2065d2897fd 100644 --- a/pkg/registry/authorization/selfsubjectrulesreview/rest.go +++ b/pkg/registry/authorization/selfsubjectrulesreview/rest.go @@ -95,6 +95,12 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation return ret, nil } +var _ rest.SingularNameProvider = &REST{} + +func (r *REST) GetSingularName() string { + return "selfsubjectrulesreview" +} + func getResourceRules(infos []authorizer.ResourceRuleInfo) []authorizationapi.ResourceRule { rules := make([]authorizationapi.ResourceRule, len(infos)) for i, info := range infos { diff --git a/pkg/registry/authorization/subjectaccessreview/rest.go b/pkg/registry/authorization/subjectaccessreview/rest.go index 4bb2072a5f7..5a6edb56451 100644 --- a/pkg/registry/authorization/subjectaccessreview/rest.go +++ b/pkg/registry/authorization/subjectaccessreview/rest.go @@ -52,6 +52,12 @@ func (r *REST) Destroy() { // here explicitly. } +var _ rest.SingularNameProvider = &REST{} + +func (r *REST) GetSingularName() string { + return "subjectaccessreview" +} + func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { subjectAccessReview, ok := obj.(*authorizationapi.SubjectAccessReview) if !ok { diff --git a/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go b/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go index 44a7911eea3..01677f5af12 100644 --- a/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go +++ b/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go @@ -40,9 +40,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against horizontal pod autoscalers. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscaler{} }, - NewListFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscalerList{} }, - DefaultQualifiedResource: autoscaling.Resource("horizontalpodautoscalers"), + NewFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscaler{} }, + NewListFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscalerList{} }, + DefaultQualifiedResource: autoscaling.Resource("horizontalpodautoscalers"), + SingularQualifiedResource: autoscaling.Resource("horizontalpodautoscaler"), CreateStrategy: horizontalpodautoscaler.Strategy, UpdateStrategy: horizontalpodautoscaler.Strategy, @@ -78,13 +79,6 @@ func (r *REST) Categories() []string { return []string{"all"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "horizontalpodautoscaler" -} - // StatusREST implements the REST endpoint for changing the status of a daemonset type StatusREST struct { store *genericregistry.Store @@ -121,3 +115,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage_test.go b/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage_test.go index bf269222cd9..589932db37f 100644 --- a/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage_test.go +++ b/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage_test.go @@ -176,14 +176,6 @@ func TestCategories(t *testing.T) { registrytest.AssertCategories(t, storage, expected) } -func TestSingularName(t *testing.T) { - storage, _, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "horizontalpodautoscaler" - registrytest.AssertSingularName(t, storage, expected) -} - func TestUpdateStatus(t *testing.T) { storage, statusStorage, server := newStorage(t) defer server.Terminate(t) diff --git a/pkg/registry/batch/cronjob/storage/storage.go b/pkg/registry/batch/cronjob/storage/storage.go index 51d453bfe74..52abf8d4a49 100644 --- a/pkg/registry/batch/cronjob/storage/storage.go +++ b/pkg/registry/batch/cronjob/storage/storage.go @@ -40,9 +40,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against CronJobs. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &batch.CronJob{} }, - NewListFunc: func() runtime.Object { return &batch.CronJobList{} }, - DefaultQualifiedResource: batch.Resource("cronjobs"), + NewFunc: func() runtime.Object { return &batch.CronJob{} }, + NewListFunc: func() runtime.Object { return &batch.CronJobList{} }, + DefaultQualifiedResource: batch.Resource("cronjobs"), + SingularQualifiedResource: batch.Resource("cronjob"), CreateStrategy: cronjob.Strategy, UpdateStrategy: cronjob.Strategy, @@ -76,13 +77,6 @@ func (r *REST) ShortNames() []string { return []string{"cj"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "cronjob" -} - // StatusREST implements the REST endpoint for changing the status of a resourcequota. type StatusREST struct { store *genericregistry.Store @@ -119,3 +113,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/batch/job/storage/storage.go b/pkg/registry/batch/job/storage/storage.go index 93c6eb8b606..fbd509bf919 100644 --- a/pkg/registry/batch/job/storage/storage.go +++ b/pkg/registry/batch/job/storage/storage.go @@ -64,10 +64,11 @@ type REST struct { // NewREST returns a RESTStorage object that will work against Jobs. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &batch.Job{} }, - NewListFunc: func() runtime.Object { return &batch.JobList{} }, - PredicateFunc: job.MatchJob, - DefaultQualifiedResource: batch.Resource("jobs"), + NewFunc: func() runtime.Object { return &batch.Job{} }, + NewListFunc: func() runtime.Object { return &batch.JobList{} }, + PredicateFunc: job.MatchJob, + DefaultQualifiedResource: batch.Resource("jobs"), + SingularQualifiedResource: batch.Resource("job"), CreateStrategy: job.Strategy, UpdateStrategy: job.Strategy, @@ -96,13 +97,6 @@ func (r *REST) Categories() []string { return []string{"all"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "job" -} - func (r *REST) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) { //nolint:staticcheck // SA1019 backwards compatibility //nolint: staticcheck @@ -162,3 +156,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/batch/job/storage/storage_test.go b/pkg/registry/batch/job/storage/storage_test.go index 5b9b991f61c..765b3179509 100644 --- a/pkg/registry/batch/job/storage/storage_test.go +++ b/pkg/registry/batch/job/storage/storage_test.go @@ -375,11 +375,3 @@ func TestCategories(t *testing.T) { expected := []string{"all"} registrytest.AssertCategories(t, storage.Job, expected) } - -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Job.Store.DestroyFunc() - expected := "job" - registrytest.AssertSingularName(t, storage.Job, expected) -} diff --git a/pkg/registry/certificates/certificates/storage/storage.go b/pkg/registry/certificates/certificates/storage/storage.go index 5c72cc2be68..2a477369f12 100644 --- a/pkg/registry/certificates/certificates/storage/storage.go +++ b/pkg/registry/certificates/certificates/storage/storage.go @@ -40,9 +40,10 @@ type REST struct { // NewREST returns a registry which will store CertificateSigningRequest in the given helper. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *ApprovalREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &certificates.CertificateSigningRequest{} }, - NewListFunc: func() runtime.Object { return &certificates.CertificateSigningRequestList{} }, - DefaultQualifiedResource: certificates.Resource("certificatesigningrequests"), + NewFunc: func() runtime.Object { return &certificates.CertificateSigningRequest{} }, + NewListFunc: func() runtime.Object { return &certificates.CertificateSigningRequestList{} }, + DefaultQualifiedResource: certificates.Resource("certificatesigningrequests"), + SingularQualifiedResource: certificates.Resource("certificatesigningrequest"), CreateStrategy: csrregistry.Strategy, UpdateStrategy: csrregistry.Strategy, @@ -79,13 +80,6 @@ func (r *REST) ShortNames() []string { return []string{"csr"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "certificatesigningrequest" -} - // StatusREST implements the REST endpoint for changing the status of a CSR. type StatusREST struct { store *genericregistry.Store @@ -123,6 +117,12 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, return r.store.ConvertToTable(ctx, object, tableOptions) } +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} + var _ = rest.Patcher(&StatusREST{}) // ApprovalREST implements the REST endpoint for changing the approval state of a CSR. @@ -158,4 +158,10 @@ func (r *ApprovalREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set return r.store.GetResetFields() } +var _ rest.SingularNameProvider = &ApprovalREST{} + +func (r *ApprovalREST) GetSingularName() string { + return r.store.GetSingularName() +} + var _ = rest.Patcher(&ApprovalREST{}) diff --git a/pkg/registry/coordination/lease/storage/storage.go b/pkg/registry/coordination/lease/storage/storage.go index a0f67bc2ff4..5b890bcf507 100644 --- a/pkg/registry/coordination/lease/storage/storage.go +++ b/pkg/registry/coordination/lease/storage/storage.go @@ -20,7 +20,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" - "k8s.io/apiserver/pkg/registry/rest" coordinationapi "k8s.io/kubernetes/pkg/apis/coordination" "k8s.io/kubernetes/pkg/printers" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" @@ -36,9 +35,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against leases. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &coordinationapi.Lease{} }, - NewListFunc: func() runtime.Object { return &coordinationapi.LeaseList{} }, - DefaultQualifiedResource: coordinationapi.Resource("leases"), + NewFunc: func() runtime.Object { return &coordinationapi.Lease{} }, + NewListFunc: func() runtime.Object { return &coordinationapi.LeaseList{} }, + DefaultQualifiedResource: coordinationapi.Resource("leases"), + SingularQualifiedResource: coordinationapi.Resource("lease"), CreateStrategy: lease.Strategy, UpdateStrategy: lease.Strategy, @@ -53,10 +53,3 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { return &REST{store}, nil } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "lease" -} diff --git a/pkg/registry/core/componentstatus/rest.go b/pkg/registry/core/componentstatus/rest.go index 22fe41a0c84..4539217a674 100644 --- a/pkg/registry/core/componentstatus/rest.go +++ b/pkg/registry/core/componentstatus/rest.go @@ -58,6 +58,12 @@ func (rs *REST) New() runtime.Object { return &api.ComponentStatus{} } +var _ rest.SingularNameProvider = &REST{} + +func (rs *REST) GetSingularName() string { + return "componentstatus" +} + // Destroy cleans up resources on shutdown. func (r *REST) Destroy() { // Given no underlying store, we don't destroy anything diff --git a/pkg/registry/core/configmap/storage/storage.go b/pkg/registry/core/configmap/storage/storage.go index 47648ded842..14e64a53936 100644 --- a/pkg/registry/core/configmap/storage/storage.go +++ b/pkg/registry/core/configmap/storage/storage.go @@ -37,10 +37,11 @@ type REST struct { // NewREST returns a RESTStorage object that will work with ConfigMap objects. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.ConfigMap{} }, - NewListFunc: func() runtime.Object { return &api.ConfigMapList{} }, - PredicateFunc: configmap.Matcher, - DefaultQualifiedResource: api.Resource("configmaps"), + NewFunc: func() runtime.Object { return &api.ConfigMap{} }, + NewListFunc: func() runtime.Object { return &api.ConfigMapList{} }, + PredicateFunc: configmap.Matcher, + DefaultQualifiedResource: api.Resource("configmaps"), + SingularQualifiedResource: api.Resource("configmap"), CreateStrategy: configmap.Strategy, UpdateStrategy: configmap.Strategy, @@ -66,10 +67,3 @@ var _ rest.ShortNamesProvider = &REST{} func (r *REST) ShortNames() []string { return []string{"cm"} } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "configmap" -} diff --git a/pkg/registry/core/configmap/storage/storage_test.go b/pkg/registry/core/configmap/storage/storage_test.go index 78b927d4586..04ccc8d8999 100644 --- a/pkg/registry/core/configmap/storage/storage_test.go +++ b/pkg/registry/core/configmap/storage/storage_test.go @@ -172,11 +172,3 @@ func TestShortNames(t *testing.T) { expected := []string{"cm"} registrytest.AssertShortNames(t, storage, expected) } - -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "configmap" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/pkg/registry/core/endpoint/storage/storage.go b/pkg/registry/core/endpoint/storage/storage.go index e0f36f29e73..c82deb687d1 100644 --- a/pkg/registry/core/endpoint/storage/storage.go +++ b/pkg/registry/core/endpoint/storage/storage.go @@ -36,9 +36,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against endpoints. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.Endpoints{} }, - NewListFunc: func() runtime.Object { return &api.EndpointsList{} }, - DefaultQualifiedResource: api.Resource("endpoints"), + NewFunc: func() runtime.Object { return &api.Endpoints{} }, + NewListFunc: func() runtime.Object { return &api.EndpointsList{} }, + DefaultQualifiedResource: api.Resource("endpoints"), + SingularQualifiedResource: api.Resource("endpoint"), CreateStrategy: endpoint.Strategy, UpdateStrategy: endpoint.Strategy, @@ -60,10 +61,3 @@ var _ rest.ShortNamesProvider = &REST{} func (r *REST) ShortNames() []string { return []string{"ep"} } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "endpoint" -} diff --git a/pkg/registry/core/event/storage/storage.go b/pkg/registry/core/event/storage/storage.go index 7be63d0ce60..dd2e403c1bd 100644 --- a/pkg/registry/core/event/storage/storage.go +++ b/pkg/registry/core/event/storage/storage.go @@ -42,7 +42,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter, ttl uint64) (*REST, error) { TTLFunc: func(runtime.Object, uint64, bool) (uint64, error) { return ttl, nil }, - DefaultQualifiedResource: api.Resource("events"), + DefaultQualifiedResource: api.Resource("events"), + SingularQualifiedResource: api.Resource("event"), CreateStrategy: event.Strategy, UpdateStrategy: event.Strategy, @@ -64,10 +65,3 @@ var _ rest.ShortNamesProvider = &REST{} func (r *REST) ShortNames() []string { return []string{"ev"} } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "event" -} diff --git a/pkg/registry/core/event/storage/storage_test.go b/pkg/registry/core/event/storage/storage_test.go index 854c7776050..134de72b8bf 100644 --- a/pkg/registry/core/event/storage/storage_test.go +++ b/pkg/registry/core/event/storage/storage_test.go @@ -123,11 +123,3 @@ func TestShortNames(t *testing.T) { expected := []string{"ev"} registrytest.AssertShortNames(t, storage, expected) } - -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "event" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/pkg/registry/core/limitrange/storage/storage.go b/pkg/registry/core/limitrange/storage/storage.go index b286f7f9230..d91f14204b3 100644 --- a/pkg/registry/core/limitrange/storage/storage.go +++ b/pkg/registry/core/limitrange/storage/storage.go @@ -33,9 +33,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against limit ranges. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.LimitRange{} }, - NewListFunc: func() runtime.Object { return &api.LimitRangeList{} }, - DefaultQualifiedResource: api.Resource("limitranges"), + NewFunc: func() runtime.Object { return &api.LimitRange{} }, + NewListFunc: func() runtime.Object { return &api.LimitRangeList{} }, + DefaultQualifiedResource: api.Resource("limitranges"), + SingularQualifiedResource: api.Resource("limitrange"), CreateStrategy: limitrange.Strategy, UpdateStrategy: limitrange.Strategy, @@ -58,10 +59,3 @@ var _ rest.ShortNamesProvider = &REST{} func (r *REST) ShortNames() []string { return []string{"limits"} } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "limitrange" -} diff --git a/pkg/registry/core/limitrange/storage/storage_test.go b/pkg/registry/core/limitrange/storage/storage_test.go index 38b16a3b7d0..3bbcad7f5e3 100644 --- a/pkg/registry/core/limitrange/storage/storage_test.go +++ b/pkg/registry/core/limitrange/storage/storage_test.go @@ -171,11 +171,3 @@ func TestShortNames(t *testing.T) { expected := []string{"limits"} registrytest.AssertShortNames(t, storage, expected) } - -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "limitrange" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/pkg/registry/core/namespace/storage/storage.go b/pkg/registry/core/namespace/storage/storage.go index 3201ca45498..18afd20e7f9 100644 --- a/pkg/registry/core/namespace/storage/storage.go +++ b/pkg/registry/core/namespace/storage/storage.go @@ -59,10 +59,11 @@ type FinalizeREST struct { // NewREST returns a RESTStorage object that will work against namespaces. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *FinalizeREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.Namespace{} }, - NewListFunc: func() runtime.Object { return &api.NamespaceList{} }, - PredicateFunc: namespace.MatchNamespace, - DefaultQualifiedResource: api.Resource("namespaces"), + NewFunc: func() runtime.Object { return &api.Namespace{} }, + NewListFunc: func() runtime.Object { return &api.NamespaceList{} }, + PredicateFunc: namespace.MatchNamespace, + DefaultQualifiedResource: api.Resource("namespaces"), + SingularQualifiedResource: api.Resource("namespace"), CreateStrategy: namespace.Strategy, UpdateStrategy: namespace.Strategy, @@ -94,6 +95,12 @@ func (r *REST) NamespaceScoped() bool { return r.store.NamespaceScoped() } +var _ rest.SingularNameProvider = &REST{} + +func (r *REST) GetSingularName() string { + return r.store.GetSingularName() +} + func (r *REST) New() runtime.Object { return r.store.New() } @@ -291,13 +298,6 @@ func (r *REST) ShortNames() []string { return []string{"ns"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "namespace" -} - var _ rest.StorageVersionProvider = &REST{} func (r *REST) StorageVersion() runtime.GroupVersioner { @@ -339,6 +339,12 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, return r.store.ConvertToTable(ctx, object, tableOptions) } +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} + func (r *FinalizeREST) New() runtime.Object { return r.store.New() } @@ -360,3 +366,9 @@ func (r *FinalizeREST) Update(ctx context.Context, name string, objInfo rest.Upd func (r *FinalizeREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { return r.store.GetResetFields() } + +var _ rest.SingularNameProvider = &FinalizeREST{} + +func (r *FinalizeREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/core/namespace/storage/storage_test.go b/pkg/registry/core/namespace/storage/storage_test.go index e94c9b3fb33..a1bfd9e9af8 100644 --- a/pkg/registry/core/namespace/storage/storage_test.go +++ b/pkg/registry/core/namespace/storage/storage_test.go @@ -628,11 +628,3 @@ func TestShortNames(t *testing.T) { expected := []string{"ns"} registrytest.AssertShortNames(t, storage, expected) } - -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.store.DestroyFunc() - expected := "namespace" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/pkg/registry/core/node/rest/proxy.go b/pkg/registry/core/node/rest/proxy.go index 40e6431b40b..4f4b855e284 100644 --- a/pkg/registry/core/node/rest/proxy.go +++ b/pkg/registry/core/node/rest/proxy.go @@ -66,6 +66,12 @@ func (r *ProxyREST) NewConnectOptions() (runtime.Object, bool, string) { return &api.NodeProxyOptions{}, true, "path" } +var _ rest.SingularNameProvider = &ProxyREST{} + +func (r *ProxyREST) GetSingularName() string { + return r.Store.GetSingularName() +} + // Connect returns a handler for the node proxy func (r *ProxyREST) Connect(ctx context.Context, id string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { proxyOpts, ok := opts.(*api.NodeProxyOptions) diff --git a/pkg/registry/core/node/storage/storage.go b/pkg/registry/core/node/storage/storage.go index e8ecf8b9fe4..faf741ebbc2 100644 --- a/pkg/registry/core/node/storage/storage.go +++ b/pkg/registry/core/node/storage/storage.go @@ -93,13 +93,20 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, return r.store.ConvertToTable(ctx, object, tableOptions) } +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} + // NewStorage returns a NodeStorage object that will work against nodes. func NewStorage(optsGetter generic.RESTOptionsGetter, kubeletClientConfig client.KubeletClientConfig, proxyTransport http.RoundTripper) (*NodeStorage, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.Node{} }, - NewListFunc: func() runtime.Object { return &api.NodeList{} }, - PredicateFunc: node.MatchNode, - DefaultQualifiedResource: api.Resource("nodes"), + NewFunc: func() runtime.Object { return &api.Node{} }, + NewListFunc: func() runtime.Object { return &api.NodeList{} }, + PredicateFunc: node.MatchNode, + DefaultQualifiedResource: api.Resource("nodes"), + SingularQualifiedResource: api.Resource("node"), CreateStrategy: node.Strategy, UpdateStrategy: node.Strategy, @@ -174,10 +181,3 @@ var _ rest.ShortNamesProvider = &REST{} func (r *REST) ShortNames() []string { return []string{"no"} } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "node" -} diff --git a/pkg/registry/core/persistentvolume/storage/storage.go b/pkg/registry/core/persistentvolume/storage/storage.go index 06bd7beeb4c..6809f1ee2ba 100644 --- a/pkg/registry/core/persistentvolume/storage/storage.go +++ b/pkg/registry/core/persistentvolume/storage/storage.go @@ -40,10 +40,11 @@ type REST struct { // NewREST returns a RESTStorage object that will work against persistent volumes. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.PersistentVolume{} }, - NewListFunc: func() runtime.Object { return &api.PersistentVolumeList{} }, - PredicateFunc: persistentvolume.MatchPersistentVolumes, - DefaultQualifiedResource: api.Resource("persistentvolumes"), + NewFunc: func() runtime.Object { return &api.PersistentVolume{} }, + NewListFunc: func() runtime.Object { return &api.PersistentVolumeList{} }, + PredicateFunc: persistentvolume.MatchPersistentVolumes, + DefaultQualifiedResource: api.Resource("persistentvolumes"), + SingularQualifiedResource: api.Resource("persistentvolume"), CreateStrategy: persistentvolume.Strategy, UpdateStrategy: persistentvolume.Strategy, @@ -73,13 +74,6 @@ func (r *REST) ShortNames() []string { return []string{"pv"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "persistentvolume" -} - // StatusREST implements the REST endpoint for changing the status of a persistentvolume. type StatusREST struct { store *genericregistry.Store @@ -116,3 +110,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/core/persistentvolume/storage/storage_test.go b/pkg/registry/core/persistentvolume/storage/storage_test.go index 5c8a7b5bdce..c03fa3248a9 100644 --- a/pkg/registry/core/persistentvolume/storage/storage_test.go +++ b/pkg/registry/core/persistentvolume/storage/storage_test.go @@ -208,11 +208,3 @@ func TestShortNames(t *testing.T) { expected := []string{"pv"} registrytest.AssertShortNames(t, storage, expected) } - -func TestSingularName(t *testing.T) { - storage, _, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "persistentvolume" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/pkg/registry/core/persistentvolumeclaim/storage/storage.go b/pkg/registry/core/persistentvolumeclaim/storage/storage.go index 26e6d80c867..b580693fc17 100644 --- a/pkg/registry/core/persistentvolumeclaim/storage/storage.go +++ b/pkg/registry/core/persistentvolumeclaim/storage/storage.go @@ -41,10 +41,11 @@ type REST struct { // NewREST returns a RESTStorage object that will work against persistent volume claims. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.PersistentVolumeClaim{} }, - NewListFunc: func() runtime.Object { return &api.PersistentVolumeClaimList{} }, - PredicateFunc: persistentvolumeclaim.MatchPersistentVolumeClaim, - DefaultQualifiedResource: api.Resource("persistentvolumeclaims"), + NewFunc: func() runtime.Object { return &api.PersistentVolumeClaim{} }, + NewListFunc: func() runtime.Object { return &api.PersistentVolumeClaimList{} }, + PredicateFunc: persistentvolumeclaim.MatchPersistentVolumeClaim, + DefaultQualifiedResource: api.Resource("persistentvolumeclaims"), + SingularQualifiedResource: api.Resource("persistentvolumeclaim"), CreateStrategy: persistentvolumeclaim.Strategy, UpdateStrategy: persistentvolumeclaim.Strategy, @@ -77,13 +78,6 @@ func (r *REST) ShortNames() []string { return []string{"pvc"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "persistentvolumeclaim" -} - // defaultOnRead sets interlinked fields that were not previously set on read. // We can't do this in the normal defaulting path because that same logic // applies on Get, Create, and Update, but we need to distinguish between them. @@ -160,3 +154,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/core/persistentvolumeclaim/storage/storage_test.go b/pkg/registry/core/persistentvolumeclaim/storage/storage_test.go index d94fed0fcfe..54c0ca625f5 100644 --- a/pkg/registry/core/persistentvolumeclaim/storage/storage_test.go +++ b/pkg/registry/core/persistentvolumeclaim/storage/storage_test.go @@ -212,14 +212,6 @@ func TestShortNames(t *testing.T) { registrytest.AssertShortNames(t, storage, expected) } -func TestSingularName(t *testing.T) { - storage, _, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "persistentvolumeclaim" - registrytest.AssertSingularName(t, storage, expected) -} - func TestDefaultOnReadPvc(t *testing.T) { storage, _, server := newStorage(t) defer server.Terminate(t) diff --git a/pkg/registry/core/pod/rest/log.go b/pkg/registry/core/pod/rest/log.go index e6b02069b28..bd81f585727 100644 --- a/pkg/registry/core/pod/rest/log.go +++ b/pkg/registry/core/pod/rest/log.go @@ -133,3 +133,9 @@ func (r *LogREST) OverrideMetricsVerb(oldVerb string) (newVerb string) { return } + +var _ rest.SingularNameProvider = &LogREST{} + +func (r *LogREST) GetSingularName() string { + return r.Store.GetSingularName() +} diff --git a/pkg/registry/core/pod/rest/subresources.go b/pkg/registry/core/pod/rest/subresources.go index 76e0cdd4ffb..c2bdfa5b4ad 100644 --- a/pkg/registry/core/pod/rest/subresources.go +++ b/pkg/registry/core/pod/rest/subresources.go @@ -80,6 +80,12 @@ func (r *ProxyREST) Connect(ctx context.Context, id string, opts runtime.Object, return newThrottledUpgradeAwareProxyHandler(location, transport, true, false, responder), nil } +var _ rest.SingularNameProvider = &ProxyREST{} + +func (r *ProxyREST) GetSingularName() string { + return r.Store.GetSingularName() +} + // Support both GET and POST methods. We must support GET for browsers that want to use WebSockets. var upgradeableMethods = []string{"GET", "POST"} @@ -126,6 +132,12 @@ func (r *AttachREST) ConnectMethods() []string { return upgradeableMethods } +var _ rest.SingularNameProvider = &AttachREST{} + +func (r *AttachREST) GetSingularName() string { + return r.Store.GetSingularName() +} + // ExecREST implements the exec subresource for a Pod type ExecREST struct { Store *genericregistry.Store @@ -169,6 +181,12 @@ func (r *ExecREST) ConnectMethods() []string { return upgradeableMethods } +var _ rest.SingularNameProvider = &ExecREST{} + +func (r *ExecREST) GetSingularName() string { + return r.Store.GetSingularName() +} + // PortForwardREST implements the portforward subresource for a Pod type PortForwardREST struct { Store *genericregistry.Store @@ -213,6 +231,12 @@ func (r *PortForwardREST) Connect(ctx context.Context, name string, opts runtime return newThrottledUpgradeAwareProxyHandler(location, transport, false, true, responder), nil } +var _ rest.SingularNameProvider = &PortForwardREST{} + +func (r *PortForwardREST) GetSingularName() string { + return r.Store.GetSingularName() +} + func newThrottledUpgradeAwareProxyHandler(location *url.URL, transport http.RoundTripper, wrapTransport, upgradeRequired bool, responder rest.Responder) *proxy.UpgradeAwareHandler { handler := proxy.NewUpgradeAwareHandler(location, transport, wrapTransport, upgradeRequired, proxy.NewErrorResponder(responder)) handler.MaxBytesPerSec = capabilities.Get().PerConnectionBandwidthLimitBytesPerSec diff --git a/pkg/registry/core/pod/storage/eviction.go b/pkg/registry/core/pod/storage/eviction.go index ee8182c4135..87d3991b44a 100644 --- a/pkg/registry/core/pod/storage/eviction.go +++ b/pkg/registry/core/pod/storage/eviction.go @@ -103,6 +103,12 @@ func (r *EvictionREST) Destroy() { // we don't destroy it here explicitly. } +var _ rest.SingularNameProvider = &EvictionREST{} + +func (r *EvictionREST) GetSingularName() string { + return "pod" +} + // Propagate dry-run takes the dry-run option from the request and pushes it into the eviction object. // It returns an error if they have non-matching dry-run options. func propagateDryRun(eviction *policy.Eviction, options *metav1.CreateOptions) (*metav1.DeleteOptions, error) { diff --git a/pkg/registry/core/pod/storage/storage.go b/pkg/registry/core/pod/storage/storage.go index 034884960d9..ddcbde69e3d 100644 --- a/pkg/registry/core/pod/storage/storage.go +++ b/pkg/registry/core/pod/storage/storage.go @@ -73,10 +73,11 @@ type REST struct { func NewStorage(optsGetter generic.RESTOptionsGetter, k client.ConnectionInfoGetter, proxyTransport http.RoundTripper, podDisruptionBudgetClient policyclient.PodDisruptionBudgetsGetter) (PodStorage, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.Pod{} }, - NewListFunc: func() runtime.Object { return &api.PodList{} }, - PredicateFunc: registrypod.MatchPod, - DefaultQualifiedResource: api.Resource("pods"), + NewFunc: func() runtime.Object { return &api.Pod{} }, + NewListFunc: func() runtime.Object { return &api.PodList{} }, + PredicateFunc: registrypod.MatchPod, + DefaultQualifiedResource: api.Resource("pods"), + SingularQualifiedResource: api.Resource("pod"), CreateStrategy: registrypod.Strategy, UpdateStrategy: registrypod.Strategy, @@ -142,13 +143,6 @@ func (r *REST) Categories() []string { return []string{"all"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "pod" -} - // BindingREST implements the REST endpoint for binding pods to nodes when etcd is in use. type BindingREST struct { store *genericregistry.Store @@ -170,6 +164,12 @@ func (r *BindingREST) Destroy() { // we don't destroy it here explicitly. } +var _ rest.SingularNameProvider = &BindingREST{} + +func (r *BindingREST) GetSingularName() string { + return r.store.GetSingularName() +} + var _ = rest.NamedCreater(&BindingREST{}) // Create ensures a pod is bound to a specific host. @@ -286,6 +286,12 @@ func (r *LegacyBindingREST) Destroy() { // we don't destroy it here explicitly. } +var _ rest.SingularNameProvider = &LegacyBindingREST{} + +func (r *LegacyBindingREST) GetSingularName() string { + return r.bindingRest.GetSingularName() +} + // Create ensures a pod is bound to a specific host. func (r *LegacyBindingREST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (out runtime.Object, err error) { metadata, err := meta.Accessor(obj) @@ -332,6 +338,12 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, return r.store.ConvertToTable(ctx, object, tableOptions) } +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} + // EphemeralContainersREST implements the REST endpoint for adding EphemeralContainers type EphemeralContainersREST struct { store *genericregistry.Store @@ -361,3 +373,9 @@ func (r *EphemeralContainersREST) Update(ctx context.Context, name string, objIn // subresources should never allow create on update. return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options) } + +var _ rest.SingularNameProvider = &EphemeralContainersREST{} + +func (r *EphemeralContainersREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/core/pod/storage/storage_test.go b/pkg/registry/core/pod/storage/storage_test.go index dc7160078c4..1e15ca8a834 100644 --- a/pkg/registry/core/pod/storage/storage_test.go +++ b/pkg/registry/core/pod/storage/storage_test.go @@ -1274,11 +1274,3 @@ func TestCategories(t *testing.T) { expected := []string{"all"} registrytest.AssertCategories(t, storage, expected) } - -func TestSingularName(t *testing.T) { - storage, _, _, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "pod" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/pkg/registry/core/podtemplate/storage/storage.go b/pkg/registry/core/podtemplate/storage/storage.go index 66d267d6777..dfc160569d0 100644 --- a/pkg/registry/core/podtemplate/storage/storage.go +++ b/pkg/registry/core/podtemplate/storage/storage.go @@ -20,7 +20,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" - "k8s.io/apiserver/pkg/registry/rest" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/printers" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" @@ -36,9 +35,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against pod templates. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.PodTemplate{} }, - NewListFunc: func() runtime.Object { return &api.PodTemplateList{} }, - DefaultQualifiedResource: api.Resource("podtemplates"), + NewFunc: func() runtime.Object { return &api.PodTemplate{} }, + NewListFunc: func() runtime.Object { return &api.PodTemplateList{} }, + DefaultQualifiedResource: api.Resource("podtemplates"), + SingularQualifiedResource: api.Resource("podtemplate"), CreateStrategy: podtemplate.Strategy, UpdateStrategy: podtemplate.Strategy, @@ -54,10 +54,3 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { } return &REST{store}, nil } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "podtemplate" -} diff --git a/pkg/registry/core/podtemplate/storage/storage_test.go b/pkg/registry/core/podtemplate/storage/storage_test.go index 59c3413f902..785fc6fcb62 100644 --- a/pkg/registry/core/podtemplate/storage/storage_test.go +++ b/pkg/registry/core/podtemplate/storage/storage_test.go @@ -153,11 +153,3 @@ func TestWatch(t *testing.T) { }, ) } - -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "podtemplate" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/pkg/registry/core/replicationcontroller/storage/storage.go b/pkg/registry/core/replicationcontroller/storage/storage.go index d5fca9c0f96..e21d599379a 100644 --- a/pkg/registry/core/replicationcontroller/storage/storage.go +++ b/pkg/registry/core/replicationcontroller/storage/storage.go @@ -82,10 +82,11 @@ type REST struct { // NewREST returns a RESTStorage object that will work against replication controllers. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.ReplicationController{} }, - NewListFunc: func() runtime.Object { return &api.ReplicationControllerList{} }, - PredicateFunc: replicationcontroller.MatchController, - DefaultQualifiedResource: api.Resource("replicationcontrollers"), + NewFunc: func() runtime.Object { return &api.ReplicationController{} }, + NewListFunc: func() runtime.Object { return &api.ReplicationControllerList{} }, + PredicateFunc: replicationcontroller.MatchController, + DefaultQualifiedResource: api.Resource("replicationcontrollers"), + SingularQualifiedResource: api.Resource("replicationcontroller"), CreateStrategy: replicationcontroller.Strategy, UpdateStrategy: replicationcontroller.Strategy, @@ -122,13 +123,6 @@ func (r *REST) Categories() []string { return []string{"all"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "replicationcontroller" -} - // StatusREST implements the REST endpoint for changing the status of a replication controller type StatusREST struct { store *genericregistry.Store @@ -165,6 +159,12 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, return r.store.ConvertToTable(ctx, object, tableOptions) } +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} + type ScaleREST struct { store *genericregistry.Store } @@ -223,6 +223,12 @@ func (r *ScaleREST) ConvertToTable(ctx context.Context, object runtime.Object, t return r.store.ConvertToTable(ctx, object, tableOptions) } +var _ rest.SingularNameProvider = &ScaleREST{} + +func (r *ScaleREST) GetSingularName() string { + return r.store.GetSingularName() +} + func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc { return func(ctx context.Context, obj runtime.Object) error { return f(ctx, scaleFromRC(obj.(*api.ReplicationController))) diff --git a/pkg/registry/core/replicationcontroller/storage/storage_test.go b/pkg/registry/core/replicationcontroller/storage/storage_test.go index 60e133cb26a..009fed33b1a 100644 --- a/pkg/registry/core/replicationcontroller/storage/storage_test.go +++ b/pkg/registry/core/replicationcontroller/storage/storage_test.go @@ -352,14 +352,6 @@ func TestCategories(t *testing.T) { registrytest.AssertCategories(t, storage.Controller, expected) } -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Controller.Store.DestroyFunc() - expected := "replicationcontroller" - registrytest.AssertSingularName(t, storage.Controller, expected) -} - func TestScalePatchErrors(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) diff --git a/pkg/registry/core/resourcequota/storage/storage.go b/pkg/registry/core/resourcequota/storage/storage.go index 76b71dd2096..25f7e93c5e3 100644 --- a/pkg/registry/core/resourcequota/storage/storage.go +++ b/pkg/registry/core/resourcequota/storage/storage.go @@ -40,9 +40,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against resource quotas. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.ResourceQuota{} }, - NewListFunc: func() runtime.Object { return &api.ResourceQuotaList{} }, - DefaultQualifiedResource: api.Resource("resourcequotas"), + NewFunc: func() runtime.Object { return &api.ResourceQuota{} }, + NewListFunc: func() runtime.Object { return &api.ResourceQuotaList{} }, + DefaultQualifiedResource: api.Resource("resourcequotas"), + SingularQualifiedResource: api.Resource("resourcequota"), CreateStrategy: resourcequota.Strategy, UpdateStrategy: resourcequota.Strategy, @@ -72,13 +73,6 @@ func (r *REST) ShortNames() []string { return []string{"quota"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "resourcequota" -} - // StatusREST implements the REST endpoint for changing the status of a resourcequota. type StatusREST struct { store *genericregistry.Store @@ -115,3 +109,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/core/resourcequota/storage/storage_test.go b/pkg/registry/core/resourcequota/storage/storage_test.go index 8459c32bf7f..9b750553f83 100644 --- a/pkg/registry/core/resourcequota/storage/storage_test.go +++ b/pkg/registry/core/resourcequota/storage/storage_test.go @@ -217,11 +217,3 @@ func TestShortNames(t *testing.T) { expected := []string{"quota"} registrytest.AssertShortNames(t, storage, expected) } - -func TestSingularName(t *testing.T) { - storage, _, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "resourcequota" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/pkg/registry/core/secret/storage/storage.go b/pkg/registry/core/secret/storage/storage.go index b02cb83546c..c329c414761 100644 --- a/pkg/registry/core/secret/storage/storage.go +++ b/pkg/registry/core/secret/storage/storage.go @@ -20,7 +20,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" - "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/printers" @@ -37,10 +36,11 @@ type REST struct { // NewREST returns a RESTStorage object that will work against secrets. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.Secret{} }, - NewListFunc: func() runtime.Object { return &api.SecretList{} }, - PredicateFunc: secret.Matcher, - DefaultQualifiedResource: api.Resource("secrets"), + NewFunc: func() runtime.Object { return &api.Secret{} }, + NewListFunc: func() runtime.Object { return &api.SecretList{} }, + PredicateFunc: secret.Matcher, + DefaultQualifiedResource: api.Resource("secrets"), + SingularQualifiedResource: api.Resource("secret"), CreateStrategy: secret.Strategy, UpdateStrategy: secret.Strategy, @@ -58,10 +58,3 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { } return &REST{store}, nil } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "secret" -} diff --git a/pkg/registry/core/secret/storage/storage_test.go b/pkg/registry/core/secret/storage/storage_test.go index 68bc7dcb5fb..a3850a2dafe 100644 --- a/pkg/registry/core/secret/storage/storage_test.go +++ b/pkg/registry/core/secret/storage/storage_test.go @@ -143,11 +143,3 @@ func TestWatch(t *testing.T) { }, ) } - -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "secret" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/pkg/registry/core/service/proxy.go b/pkg/registry/core/service/proxy.go index f0eb9d0788a..c64caf5935a 100644 --- a/pkg/registry/core/service/proxy.go +++ b/pkg/registry/core/service/proxy.go @@ -77,6 +77,12 @@ func (r *ProxyREST) Connect(ctx context.Context, id string, opts runtime.Object, return newThrottledUpgradeAwareProxyHandler(location, transport, true, false, responder), nil } +var _ rest.SingularNameProvider = &ProxyREST{} + +func (r *ProxyREST) GetSingularName() string { + return "service" +} + func newThrottledUpgradeAwareProxyHandler(location *url.URL, transport http.RoundTripper, wrapTransport, upgradeRequired bool, responder rest.Responder) *proxy.UpgradeAwareHandler { handler := proxy.NewUpgradeAwareHandler(location, transport, wrapTransport, upgradeRequired, proxy.NewErrorResponder(responder)) handler.MaxBytesPerSec = capabilities.Get().PerConnectionBandwidthLimitBytesPerSec diff --git a/pkg/registry/core/service/storage/storage.go b/pkg/registry/core/service/storage/storage.go index 172135ed88e..bcacad89044 100644 --- a/pkg/registry/core/service/storage/storage.go +++ b/pkg/registry/core/service/storage/storage.go @@ -86,10 +86,11 @@ func NewREST( proxyTransport http.RoundTripper) (*REST, *StatusREST, *svcreg.ProxyREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.Service{} }, - NewListFunc: func() runtime.Object { return &api.ServiceList{} }, - DefaultQualifiedResource: api.Resource("services"), - ReturnDeletedObject: true, + NewFunc: func() runtime.Object { return &api.Service{} }, + NewListFunc: func() runtime.Object { return &api.ServiceList{} }, + DefaultQualifiedResource: api.Resource("services"), + SingularQualifiedResource: api.Resource("service"), + ReturnDeletedObject: true, CreateStrategy: svcreg.Strategy, UpdateStrategy: svcreg.Strategy, @@ -153,13 +154,6 @@ func (r *REST) Categories() []string { return []string{"all"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "service" -} - // Destroy cleans up everything on shutdown. func (r *REST) Destroy() { r.Store.Destroy() @@ -202,6 +196,12 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { return r.store.GetResetFields() } +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} + // We have a lot of functions that take a pair of "before" and "after" or // "oldSvc" and "newSvc" args. Convention across the codebase is to pass them // as (new, old), but it's easy to screw up when they are the same type. diff --git a/pkg/registry/core/service/storage/storage_test.go b/pkg/registry/core/service/storage/storage_test.go index 1cb514132df..1345ed519fa 100644 --- a/pkg/registry/core/service/storage/storage_test.go +++ b/pkg/registry/core/service/storage/storage_test.go @@ -279,14 +279,6 @@ func TestGenericCategories(t *testing.T) { registrytest.AssertCategories(t, storage, expected) } -func TestSingularName(t *testing.T) { - storage, _, server := newStorage(t, []api.IPFamily{api.IPv4Protocol}) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "service" - registrytest.AssertSingularName(t, storage, expected) -} - // // Tests of internal functions // diff --git a/pkg/registry/core/serviceaccount/storage/storage.go b/pkg/registry/core/serviceaccount/storage/storage.go index d44573bf607..0bdcf07282d 100644 --- a/pkg/registry/core/serviceaccount/storage/storage.go +++ b/pkg/registry/core/serviceaccount/storage/storage.go @@ -41,9 +41,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against service accounts. func NewREST(optsGetter generic.RESTOptionsGetter, issuer token.TokenGenerator, auds authenticator.Audiences, max time.Duration, podStorage, secretStorage *genericregistry.Store, extendExpiration bool) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.ServiceAccount{} }, - NewListFunc: func() runtime.Object { return &api.ServiceAccountList{} }, - DefaultQualifiedResource: api.Resource("serviceaccounts"), + NewFunc: func() runtime.Object { return &api.ServiceAccount{} }, + NewListFunc: func() runtime.Object { return &api.ServiceAccountList{} }, + DefaultQualifiedResource: api.Resource("serviceaccounts"), + SingularQualifiedResource: api.Resource("serviceaccount"), CreateStrategy: serviceaccount.Strategy, UpdateStrategy: serviceaccount.Strategy, @@ -84,10 +85,3 @@ var _ rest.ShortNamesProvider = &REST{} func (r *REST) ShortNames() []string { return []string{"sa"} } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "serviceaccount" -} diff --git a/pkg/registry/core/serviceaccount/storage/storage_test.go b/pkg/registry/core/serviceaccount/storage/storage_test.go index dfaaa30b315..220f5053047 100644 --- a/pkg/registry/core/serviceaccount/storage/storage_test.go +++ b/pkg/registry/core/serviceaccount/storage/storage_test.go @@ -146,11 +146,3 @@ func TestShortNames(t *testing.T) { expected := []string{"sa"} registrytest.AssertShortNames(t, storage, expected) } - -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "serviceaccount" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/pkg/registry/core/serviceaccount/storage/token.go b/pkg/registry/core/serviceaccount/storage/token.go index 6f840e53154..b59bb8d764c 100644 --- a/pkg/registry/core/serviceaccount/storage/token.go +++ b/pkg/registry/core/serviceaccount/storage/token.go @@ -49,6 +49,12 @@ func (r *TokenREST) Destroy() { // here explicitly. } +var _ rest.SingularNameProvider = &TokenREST{} + +func (r *TokenREST) GetSingularName() string { + return "serviceaccount" +} + type TokenREST struct { svcaccts getter pods getter diff --git a/pkg/registry/discovery/endpointslice/storage/storage.go b/pkg/registry/discovery/endpointslice/storage/storage.go index d8b4d1b9113..2a0286562e3 100644 --- a/pkg/registry/discovery/endpointslice/storage/storage.go +++ b/pkg/registry/discovery/endpointslice/storage/storage.go @@ -20,7 +20,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" - "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/discovery" "k8s.io/kubernetes/pkg/printers" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" @@ -36,9 +35,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against endpoint slices. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &discovery.EndpointSlice{} }, - NewListFunc: func() runtime.Object { return &discovery.EndpointSliceList{} }, - DefaultQualifiedResource: discovery.Resource("endpointslices"), + NewFunc: func() runtime.Object { return &discovery.EndpointSlice{} }, + NewListFunc: func() runtime.Object { return &discovery.EndpointSliceList{} }, + DefaultQualifiedResource: discovery.Resource("endpointslices"), + SingularQualifiedResource: discovery.Resource("endpointslice"), CreateStrategy: endpointslice.Strategy, UpdateStrategy: endpointslice.Strategy, @@ -52,10 +52,3 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { } return &REST{store}, nil } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "endpointslice" -} diff --git a/pkg/registry/flowcontrol/flowschema/storage/storage.go b/pkg/registry/flowcontrol/flowschema/storage/storage.go index d1d287e735f..380b309004f 100644 --- a/pkg/registry/flowcontrol/flowschema/storage/storage.go +++ b/pkg/registry/flowcontrol/flowschema/storage/storage.go @@ -46,9 +46,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against flow schemas. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &flowcontrol.FlowSchema{} }, - NewListFunc: func() runtime.Object { return &flowcontrol.FlowSchemaList{} }, - DefaultQualifiedResource: flowcontrol.Resource("flowschemas"), + NewFunc: func() runtime.Object { return &flowcontrol.FlowSchema{} }, + NewListFunc: func() runtime.Object { return &flowcontrol.FlowSchemaList{} }, + DefaultQualifiedResource: flowcontrol.Resource("flowschemas"), + SingularQualifiedResource: flowcontrol.Resource("flowschema"), CreateStrategy: flowschema.Strategy, UpdateStrategy: flowschema.Strategy, @@ -107,3 +108,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/flowcontrol/prioritylevelconfiguration/storage/storage.go b/pkg/registry/flowcontrol/prioritylevelconfiguration/storage/storage.go index defbd608b66..0943814184f 100644 --- a/pkg/registry/flowcontrol/prioritylevelconfiguration/storage/storage.go +++ b/pkg/registry/flowcontrol/prioritylevelconfiguration/storage/storage.go @@ -46,9 +46,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against priority level configuration. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &flowcontrol.PriorityLevelConfiguration{} }, - NewListFunc: func() runtime.Object { return &flowcontrol.PriorityLevelConfigurationList{} }, - DefaultQualifiedResource: flowcontrol.Resource("prioritylevelconfigurations"), + NewFunc: func() runtime.Object { return &flowcontrol.PriorityLevelConfiguration{} }, + NewListFunc: func() runtime.Object { return &flowcontrol.PriorityLevelConfigurationList{} }, + DefaultQualifiedResource: flowcontrol.Resource("prioritylevelconfigurations"), + SingularQualifiedResource: flowcontrol.Resource("prioritylevelconfiguration"), CreateStrategy: prioritylevelconfiguration.Strategy, UpdateStrategy: prioritylevelconfiguration.Strategy, @@ -107,3 +108,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/networking/clustercidr/storage/storage.go b/pkg/registry/networking/clustercidr/storage/storage.go index 36e93efc069..3c0f44b9ff8 100644 --- a/pkg/registry/networking/clustercidr/storage/storage.go +++ b/pkg/registry/networking/clustercidr/storage/storage.go @@ -36,9 +36,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against ClusterCIDRs. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &networkingapi.ClusterCIDR{} }, - NewListFunc: func() runtime.Object { return &networkingapi.ClusterCIDRList{} }, - DefaultQualifiedResource: networkingapi.Resource("clustercidrs"), + NewFunc: func() runtime.Object { return &networkingapi.ClusterCIDR{} }, + NewListFunc: func() runtime.Object { return &networkingapi.ClusterCIDRList{} }, + DefaultQualifiedResource: networkingapi.Resource("clustercidrs"), + SingularQualifiedResource: networkingapi.Resource("clustercidr"), CreateStrategy: clustercidr.Strategy, UpdateStrategy: clustercidr.Strategy, diff --git a/pkg/registry/networking/ingress/storage/storage.go b/pkg/registry/networking/ingress/storage/storage.go index dd82551cb1d..8ca09f81014 100644 --- a/pkg/registry/networking/ingress/storage/storage.go +++ b/pkg/registry/networking/ingress/storage/storage.go @@ -40,9 +40,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against replication controllers. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &networking.Ingress{} }, - NewListFunc: func() runtime.Object { return &networking.IngressList{} }, - DefaultQualifiedResource: networking.Resource("ingresses"), + NewFunc: func() runtime.Object { return &networking.Ingress{} }, + NewListFunc: func() runtime.Object { return &networking.IngressList{} }, + DefaultQualifiedResource: networking.Resource("ingresses"), + SingularQualifiedResource: networking.Resource("ingress"), CreateStrategy: ingress.Strategy, UpdateStrategy: ingress.Strategy, @@ -70,13 +71,6 @@ func (r *REST) ShortNames() []string { return []string{"ing"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "ingress" -} - // StatusREST implements the REST endpoint for changing the status of an ingress type StatusREST struct { store *genericregistry.Store @@ -113,3 +107,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/networking/ingress/storage/storage_test.go b/pkg/registry/networking/ingress/storage/storage_test.go index 199ea5002e9..28c42ea1c48 100644 --- a/pkg/registry/networking/ingress/storage/storage_test.go +++ b/pkg/registry/networking/ingress/storage/storage_test.go @@ -250,12 +250,4 @@ func TestShortNames(t *testing.T) { registrytest.AssertShortNames(t, storage, expected) } -func TestSingularName(t *testing.T) { - storage, _, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "ingress" - registrytest.AssertSingularName(t, storage, expected) -} - // TODO TestUpdateStatus diff --git a/pkg/registry/networking/ingressclass/storage/storage.go b/pkg/registry/networking/ingressclass/storage/storage.go index 889b7398011..932b0aba90d 100644 --- a/pkg/registry/networking/ingressclass/storage/storage.go +++ b/pkg/registry/networking/ingressclass/storage/storage.go @@ -20,7 +20,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" - "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/networking" "k8s.io/kubernetes/pkg/printers" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" @@ -36,9 +35,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against replication controllers. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &networking.IngressClass{} }, - NewListFunc: func() runtime.Object { return &networking.IngressClassList{} }, - DefaultQualifiedResource: networking.Resource("ingressclasses"), + NewFunc: func() runtime.Object { return &networking.IngressClass{} }, + NewListFunc: func() runtime.Object { return &networking.IngressClassList{} }, + DefaultQualifiedResource: networking.Resource("ingressclasses"), + SingularQualifiedResource: networking.Resource("ingressclass"), CreateStrategy: ingressclass.Strategy, UpdateStrategy: ingressclass.Strategy, @@ -53,10 +53,3 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { return &REST{store}, nil } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "ingressclass" -} diff --git a/pkg/registry/networking/networkpolicy/storage/storage.go b/pkg/registry/networking/networkpolicy/storage/storage.go index 8f2ed82fc16..cb453485f00 100644 --- a/pkg/registry/networking/networkpolicy/storage/storage.go +++ b/pkg/registry/networking/networkpolicy/storage/storage.go @@ -41,9 +41,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against NetworkPolicies. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &networkingapi.NetworkPolicy{} }, - NewListFunc: func() runtime.Object { return &networkingapi.NetworkPolicyList{} }, - DefaultQualifiedResource: networkingapi.Resource("networkpolicies"), + NewFunc: func() runtime.Object { return &networkingapi.NetworkPolicy{} }, + NewListFunc: func() runtime.Object { return &networkingapi.NetworkPolicyList{} }, + DefaultQualifiedResource: networkingapi.Resource("networkpolicies"), + SingularQualifiedResource: networkingapi.Resource("networkpolicy"), CreateStrategy: networkpolicy.Strategy, UpdateStrategy: networkpolicy.Strategy, @@ -72,13 +73,6 @@ func (r *REST) ShortNames() []string { return []string{"netpol"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "networkpolicy" -} - // StatusREST implements the REST endpoint for changing the status of an ingress type StatusREST struct { store *genericregistry.Store @@ -111,3 +105,9 @@ func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.Updat func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { return r.store.GetResetFields() } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/networking/networkpolicy/storage/storage_test.go b/pkg/registry/networking/networkpolicy/storage/storage_test.go index 57685615099..15ab8780910 100644 --- a/pkg/registry/networking/networkpolicy/storage/storage_test.go +++ b/pkg/registry/networking/networkpolicy/storage/storage_test.go @@ -198,14 +198,6 @@ func TestShortNames(t *testing.T) { registrytest.AssertShortNames(t, storage, expected) } -func TestSingularName(t *testing.T) { - storage, _, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "networkpolicy" - registrytest.AssertSingularName(t, storage, expected) -} - func TestStatusUpdate(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.NetworkPolicyStatus, true)() storage, statusStorage, server := newStorage(t) diff --git a/pkg/registry/node/runtimeclass/storage/storage.go b/pkg/registry/node/runtimeclass/storage/storage.go index 0d2fb4ae932..1848780ec04 100644 --- a/pkg/registry/node/runtimeclass/storage/storage.go +++ b/pkg/registry/node/runtimeclass/storage/storage.go @@ -40,7 +40,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*node.RuntimeClass).Name, nil }, - DefaultQualifiedResource: node.Resource("runtimeclasses"), + DefaultQualifiedResource: node.Resource("runtimeclasses"), + SingularQualifiedResource: node.Resource("runtimeclass"), CreateStrategy: runtimeclass.Strategy, UpdateStrategy: runtimeclass.Strategy, diff --git a/pkg/registry/policy/poddisruptionbudget/storage/storage.go b/pkg/registry/policy/poddisruptionbudget/storage/storage.go index 55fb2e360f6..260645c88be 100644 --- a/pkg/registry/policy/poddisruptionbudget/storage/storage.go +++ b/pkg/registry/policy/poddisruptionbudget/storage/storage.go @@ -40,9 +40,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against pod disruption budgets. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &policyapi.PodDisruptionBudget{} }, - NewListFunc: func() runtime.Object { return &policyapi.PodDisruptionBudgetList{} }, - DefaultQualifiedResource: policyapi.Resource("poddisruptionbudgets"), + NewFunc: func() runtime.Object { return &policyapi.PodDisruptionBudget{} }, + NewListFunc: func() runtime.Object { return &policyapi.PodDisruptionBudgetList{} }, + DefaultQualifiedResource: policyapi.Resource("poddisruptionbudgets"), + SingularQualifiedResource: policyapi.Resource("poddisruptionbudget"), CreateStrategy: poddisruptionbudget.Strategy, UpdateStrategy: poddisruptionbudget.Strategy, @@ -67,13 +68,6 @@ func (r *REST) ShortNames() []string { return []string{"pdb"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "poddisruptionbudget" -} - // StatusREST implements the REST endpoint for changing the status of an podDisruptionBudget. type StatusREST struct { store *genericregistry.Store @@ -110,3 +104,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/policy/podsecuritypolicy/storage/storage.go b/pkg/registry/policy/podsecuritypolicy/storage/storage.go index 1b916ad6ce9..2b2ab96cc32 100644 --- a/pkg/registry/policy/podsecuritypolicy/storage/storage.go +++ b/pkg/registry/policy/podsecuritypolicy/storage/storage.go @@ -35,9 +35,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against PodSecurityPolicy objects. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &policy.PodSecurityPolicy{} }, - NewListFunc: func() runtime.Object { return &policy.PodSecurityPolicyList{} }, - DefaultQualifiedResource: policy.Resource("podsecuritypolicies"), + NewFunc: func() runtime.Object { return &policy.PodSecurityPolicy{} }, + NewListFunc: func() runtime.Object { return &policy.PodSecurityPolicyList{} }, + DefaultQualifiedResource: policy.Resource("podsecuritypolicies"), + SingularQualifiedResource: policy.Resource("podsecuritypolicy"), CreateStrategy: podsecuritypolicy.Strategy, UpdateStrategy: podsecuritypolicy.Strategy, diff --git a/pkg/registry/rbac/clusterrole/policybased/storage.go b/pkg/registry/rbac/clusterrole/policybased/storage.go index 047630732d9..02ba90a9597 100644 --- a/pkg/registry/rbac/clusterrole/policybased/storage.go +++ b/pkg/registry/rbac/clusterrole/policybased/storage.go @@ -124,3 +124,9 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec func hasAggregationRule(clusterRole *rbac.ClusterRole) bool { return clusterRole.AggregationRule != nil && len(clusterRole.AggregationRule.ClusterRoleSelectors) > 0 } + +var _ rest.SingularNameProvider = &Storage{} + +func (s *Storage) GetSingularName() string { + return "clusterrole" +} diff --git a/pkg/registry/rbac/clusterrole/storage/storage.go b/pkg/registry/rbac/clusterrole/storage/storage.go index aa04dd376b4..02e2c8252e3 100644 --- a/pkg/registry/rbac/clusterrole/storage/storage.go +++ b/pkg/registry/rbac/clusterrole/storage/storage.go @@ -33,9 +33,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against ClusterRole objects. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &rbac.ClusterRole{} }, - NewListFunc: func() runtime.Object { return &rbac.ClusterRoleList{} }, - DefaultQualifiedResource: rbac.Resource("clusterroles"), + NewFunc: func() runtime.Object { return &rbac.ClusterRole{} }, + NewListFunc: func() runtime.Object { return &rbac.ClusterRoleList{} }, + DefaultQualifiedResource: rbac.Resource("clusterroles"), + SingularQualifiedResource: rbac.Resource("clusterrole"), CreateStrategy: clusterrole.Strategy, UpdateStrategy: clusterrole.Strategy, @@ -51,10 +52,3 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { return &REST{store}, nil } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "clusterrole" -} diff --git a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go index ad2de28e008..3ddf0c597c4 100644 --- a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go +++ b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go @@ -127,3 +127,9 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation, forceAllowCreate, options) } + +var _ rest.SingularNameProvider = &Storage{} + +func (s *Storage) GetSingularName() string { + return "clusterrolebinding" +} diff --git a/pkg/registry/rbac/clusterrolebinding/storage/storage.go b/pkg/registry/rbac/clusterrolebinding/storage/storage.go index 7d662fd726a..dad84e2a1a7 100644 --- a/pkg/registry/rbac/clusterrolebinding/storage/storage.go +++ b/pkg/registry/rbac/clusterrolebinding/storage/storage.go @@ -20,7 +20,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" - "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/printers" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" @@ -36,9 +35,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against ClusterRoleBinding objects. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &rbac.ClusterRoleBinding{} }, - NewListFunc: func() runtime.Object { return &rbac.ClusterRoleBindingList{} }, - DefaultQualifiedResource: rbac.Resource("clusterrolebindings"), + NewFunc: func() runtime.Object { return &rbac.ClusterRoleBinding{} }, + NewListFunc: func() runtime.Object { return &rbac.ClusterRoleBindingList{} }, + DefaultQualifiedResource: rbac.Resource("clusterrolebindings"), + SingularQualifiedResource: rbac.Resource("clusterrolebinding"), CreateStrategy: clusterrolebinding.Strategy, UpdateStrategy: clusterrolebinding.Strategy, @@ -53,10 +53,3 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { return &REST{store}, nil } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "clusterrolebinding" -} diff --git a/pkg/registry/rbac/role/policybased/storage.go b/pkg/registry/rbac/role/policybased/storage.go index c113e1d0f82..97743dabde4 100644 --- a/pkg/registry/rbac/role/policybased/storage.go +++ b/pkg/registry/rbac/role/policybased/storage.go @@ -99,3 +99,9 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation, forceAllowCreate, options) } + +var _ rest.SingularNameProvider = &Storage{} + +func (s *Storage) GetSingularName() string { + return "role" +} diff --git a/pkg/registry/rbac/role/storage/storage.go b/pkg/registry/rbac/role/storage/storage.go index 1eb312c12bf..373e1eb8fa6 100644 --- a/pkg/registry/rbac/role/storage/storage.go +++ b/pkg/registry/rbac/role/storage/storage.go @@ -33,9 +33,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against Role objects. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &rbac.Role{} }, - NewListFunc: func() runtime.Object { return &rbac.RoleList{} }, - DefaultQualifiedResource: rbac.Resource("roles"), + NewFunc: func() runtime.Object { return &rbac.Role{} }, + NewListFunc: func() runtime.Object { return &rbac.RoleList{} }, + DefaultQualifiedResource: rbac.Resource("roles"), + SingularQualifiedResource: rbac.Resource("role"), CreateStrategy: role.Strategy, UpdateStrategy: role.Strategy, @@ -51,10 +52,3 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { return &REST{store}, nil } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "role" -} diff --git a/pkg/registry/rbac/rolebinding/policybased/storage.go b/pkg/registry/rbac/rolebinding/policybased/storage.go index 64883635516..48177edf81d 100644 --- a/pkg/registry/rbac/rolebinding/policybased/storage.go +++ b/pkg/registry/rbac/rolebinding/policybased/storage.go @@ -142,3 +142,9 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation, forceAllowCreate, options) } + +var _ rest.SingularNameProvider = &Storage{} + +func (s *Storage) GetSingularName() string { + return "rolebinding" +} diff --git a/pkg/registry/rbac/rolebinding/storage/storage.go b/pkg/registry/rbac/rolebinding/storage/storage.go index 8a6ee171a3d..7e9f789d7de 100644 --- a/pkg/registry/rbac/rolebinding/storage/storage.go +++ b/pkg/registry/rbac/rolebinding/storage/storage.go @@ -20,7 +20,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" - "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/printers" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" @@ -36,9 +35,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against RoleBinding objects. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &rbac.RoleBinding{} }, - NewListFunc: func() runtime.Object { return &rbac.RoleBindingList{} }, - DefaultQualifiedResource: rbac.Resource("rolebindings"), + NewFunc: func() runtime.Object { return &rbac.RoleBinding{} }, + NewListFunc: func() runtime.Object { return &rbac.RoleBindingList{} }, + DefaultQualifiedResource: rbac.Resource("rolebindings"), + SingularQualifiedResource: rbac.Resource("rolebinding"), CreateStrategy: rolebinding.Strategy, UpdateStrategy: rolebinding.Strategy, @@ -53,10 +53,3 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { return &REST{store}, nil } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "rolebinding" -} diff --git a/pkg/registry/registrytest/singularNameProvider.go b/pkg/registry/registrytest/singularNameProvider.go deleted file mode 100644 index 5056b0dd477..00000000000 --- a/pkg/registry/registrytest/singularNameProvider.go +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package registrytest - -import ( - "testing" - - "k8s.io/apiserver/pkg/registry/rest" -) - -func AssertSingularName(t *testing.T, storage rest.SingularNameProvider, expected string) { - actual := storage.SingularName() - if actual != expected { - t.Errorf("singular name not equal. expected = %v actual = %v", expected, actual) - } -} diff --git a/pkg/registry/scheduling/priorityclass/storage/storage.go b/pkg/registry/scheduling/priorityclass/storage/storage.go index b2e78035b19..428ed730131 100644 --- a/pkg/registry/scheduling/priorityclass/storage/storage.go +++ b/pkg/registry/scheduling/priorityclass/storage/storage.go @@ -41,9 +41,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against priority classes. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &scheduling.PriorityClass{} }, - NewListFunc: func() runtime.Object { return &scheduling.PriorityClassList{} }, - DefaultQualifiedResource: scheduling.Resource("priorityclasses"), + NewFunc: func() runtime.Object { return &scheduling.PriorityClass{} }, + NewListFunc: func() runtime.Object { return &scheduling.PriorityClassList{} }, + DefaultQualifiedResource: scheduling.Resource("priorityclasses"), + SingularQualifiedResource: scheduling.Resource("priorityclass"), CreateStrategy: priorityclass.Strategy, UpdateStrategy: priorityclass.Strategy, @@ -67,13 +68,6 @@ func (r *REST) ShortNames() []string { return []string{"pc"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "priorityclass" -} - // Delete ensures that system priority classes are not deleted. func (r *REST) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) { for _, spc := range schedulingapiv1.SystemPriorityClasses() { diff --git a/pkg/registry/scheduling/priorityclass/storage/storage_test.go b/pkg/registry/scheduling/priorityclass/storage/storage_test.go index a0a0ae65de0..de6eba80999 100644 --- a/pkg/registry/scheduling/priorityclass/storage/storage_test.go +++ b/pkg/registry/scheduling/priorityclass/storage/storage_test.go @@ -179,11 +179,3 @@ func TestShortNames(t *testing.T) { expected := []string{"pc"} registrytest.AssertShortNames(t, storage, expected) } - -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "priorityclass" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/pkg/registry/storage/csidriver/storage/storage.go b/pkg/registry/storage/csidriver/storage/storage.go index 3f3fea2774a..0444dc7bbd1 100644 --- a/pkg/registry/storage/csidriver/storage/storage.go +++ b/pkg/registry/storage/csidriver/storage/storage.go @@ -40,9 +40,10 @@ type REST struct { // NewStorage returns a RESTStorage object that will work against CSIDrivers func NewStorage(optsGetter generic.RESTOptionsGetter) (*CSIDriverStorage, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &storageapi.CSIDriver{} }, - NewListFunc: func() runtime.Object { return &storageapi.CSIDriverList{} }, - DefaultQualifiedResource: storageapi.Resource("csidrivers"), + NewFunc: func() runtime.Object { return &storageapi.CSIDriver{} }, + NewListFunc: func() runtime.Object { return &storageapi.CSIDriverList{} }, + DefaultQualifiedResource: storageapi.Resource("csidrivers"), + SingularQualifiedResource: storageapi.Resource("csidriver"), CreateStrategy: csidriver.Strategy, UpdateStrategy: csidriver.Strategy, diff --git a/pkg/registry/storage/csinode/storage/storage.go b/pkg/registry/storage/csinode/storage/storage.go index 6fd562f1fa0..b16b0611d3a 100644 --- a/pkg/registry/storage/csinode/storage/storage.go +++ b/pkg/registry/storage/csinode/storage/storage.go @@ -40,9 +40,10 @@ type REST struct { // NewStorage returns a RESTStorage object that will work against CSINodes func NewStorage(optsGetter generic.RESTOptionsGetter) (*CSINodeStorage, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &storageapi.CSINode{} }, - NewListFunc: func() runtime.Object { return &storageapi.CSINodeList{} }, - DefaultQualifiedResource: storageapi.Resource("csinodes"), + NewFunc: func() runtime.Object { return &storageapi.CSINode{} }, + NewListFunc: func() runtime.Object { return &storageapi.CSINodeList{} }, + DefaultQualifiedResource: storageapi.Resource("csinodes"), + SingularQualifiedResource: storageapi.Resource("csinode"), CreateStrategy: csinode.Strategy, UpdateStrategy: csinode.Strategy, diff --git a/pkg/registry/storage/csistoragecapacity/storage/storage.go b/pkg/registry/storage/csistoragecapacity/storage/storage.go index b638d96b0f0..39fb8809846 100644 --- a/pkg/registry/storage/csistoragecapacity/storage/storage.go +++ b/pkg/registry/storage/csistoragecapacity/storage/storage.go @@ -38,9 +38,10 @@ type REST struct { // NewStorage returns a RESTStorage object that will work against CSIStorageCapacity func NewStorage(optsGetter generic.RESTOptionsGetter) (*CSIStorageCapacityStorage, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &storageapi.CSIStorageCapacity{} }, - NewListFunc: func() runtime.Object { return &storageapi.CSIStorageCapacityList{} }, - DefaultQualifiedResource: storageapi.Resource("csistoragecapacities"), + NewFunc: func() runtime.Object { return &storageapi.CSIStorageCapacity{} }, + NewListFunc: func() runtime.Object { return &storageapi.CSIStorageCapacityList{} }, + DefaultQualifiedResource: storageapi.Resource("csistoragecapacities"), + SingularQualifiedResource: storageapi.Resource("csistoragecapacity"), TableConvertor: rest.NewDefaultTableConvertor(storageapi.Resource("csistoragecapacities")), diff --git a/pkg/registry/storage/storageclass/storage/storage.go b/pkg/registry/storage/storageclass/storage/storage.go index fbac3a484ef..0899299cd34 100644 --- a/pkg/registry/storage/storageclass/storage/storage.go +++ b/pkg/registry/storage/storageclass/storage/storage.go @@ -36,9 +36,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against storage classes. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &storageapi.StorageClass{} }, - NewListFunc: func() runtime.Object { return &storageapi.StorageClassList{} }, - DefaultQualifiedResource: storageapi.Resource("storageclasses"), + NewFunc: func() runtime.Object { return &storageapi.StorageClass{} }, + NewListFunc: func() runtime.Object { return &storageapi.StorageClassList{} }, + DefaultQualifiedResource: storageapi.Resource("storageclasses"), + SingularQualifiedResource: storageapi.Resource("storageclass"), CreateStrategy: storageclass.Strategy, UpdateStrategy: storageclass.Strategy, @@ -62,10 +63,3 @@ var _ rest.ShortNamesProvider = &REST{} func (r *REST) ShortNames() []string { return []string{"sc"} } - -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "storageclass" -} diff --git a/pkg/registry/storage/storageclass/storage/storage_test.go b/pkg/registry/storage/storageclass/storage/storage_test.go index 8196e5225dd..fb1a20dba23 100644 --- a/pkg/registry/storage/storageclass/storage/storage_test.go +++ b/pkg/registry/storage/storageclass/storage/storage_test.go @@ -160,11 +160,3 @@ func TestShortNames(t *testing.T) { expected := []string{"sc"} registrytest.AssertShortNames(t, storage, expected) } - -func TestSingularName(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "storageclass" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/pkg/registry/storage/volumeattachment/storage/storage.go b/pkg/registry/storage/volumeattachment/storage/storage.go index e82338fbd7f..76fd823dab0 100644 --- a/pkg/registry/storage/volumeattachment/storage/storage.go +++ b/pkg/registry/storage/volumeattachment/storage/storage.go @@ -46,9 +46,10 @@ type REST struct { // NewStorage returns a RESTStorage object that will work against VolumeAttachments func NewStorage(optsGetter generic.RESTOptionsGetter) (*VolumeAttachmentStorage, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &storageapi.VolumeAttachment{} }, - NewListFunc: func() runtime.Object { return &storageapi.VolumeAttachmentList{} }, - DefaultQualifiedResource: storageapi.Resource("volumeattachments"), + NewFunc: func() runtime.Object { return &storageapi.VolumeAttachment{} }, + NewListFunc: func() runtime.Object { return &storageapi.VolumeAttachmentList{} }, + DefaultQualifiedResource: storageapi.Resource("volumeattachments"), + SingularQualifiedResource: storageapi.Resource("volumeattachment"), CreateStrategy: volumeattachment.Strategy, UpdateStrategy: volumeattachment.Strategy, @@ -73,13 +74,6 @@ func NewStorage(optsGetter generic.RESTOptionsGetter) (*VolumeAttachmentStorage, }, nil } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "volumeattachment" -} - // StatusREST implements the REST endpoint for changing the status of a VolumeAttachment type StatusREST struct { store *genericregistry.Store @@ -118,3 +112,9 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { return r.store.ConvertToTable(ctx, object, tableOptions) } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/pkg/registry/storage/volumeattachment/storage/storage_test.go b/pkg/registry/storage/volumeattachment/storage/storage_test.go index 22c13985fed..6ff5c9f749a 100644 --- a/pkg/registry/storage/volumeattachment/storage/storage_test.go +++ b/pkg/registry/storage/volumeattachment/storage/storage_test.go @@ -200,11 +200,3 @@ func TestEtcdStatusUpdate(t *testing.T) { t.Errorf("objects differ: %v", diff.ObjectDiff(attachmentOut.Status, attachmentIn.Status)) } } - -func TestSingularName(t *testing.T) { - storage, _, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() - expected := "volumeattachment" - registrytest.AssertSingularName(t, storage, expected) -} diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go index dd654ef1a0c..ee16d524d75 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go @@ -728,6 +728,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd parameterCodec := runtime.NewParameterCodec(parameterScheme) resource := schema.GroupVersionResource{Group: crd.Spec.Group, Version: v.Name, Resource: crd.Status.AcceptedNames.Plural} + singularResource := schema.GroupVersionResource{Group: crd.Spec.Group, Version: v.Name, Resource: crd.Status.AcceptedNames.Singular} kind := schema.GroupVersionKind{Group: crd.Spec.Group, Version: v.Name, Kind: crd.Status.AcceptedNames.Kind} equivalentResourceRegistry.RegisterKindFor(resource, "", kind) @@ -797,6 +798,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd storages[v.Name] = customresource.NewStorage( resource.GroupResource(), + singularResource.GroupResource(), kind, schema.GroupVersionKind{Group: crd.Spec.Group, Version: v.Name, Kind: crd.Status.AcceptedNames.ListKind}, customresource.NewStrategy( diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go index 55876b97175..8d8226d4686 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go @@ -41,7 +41,7 @@ type CustomResourceStorage struct { Scale *ScaleREST } -func NewStorage(resource schema.GroupResource, kind, listKind schema.GroupVersionKind, strategy customResourceStrategy, optsGetter generic.RESTOptionsGetter, categories []string, tableConvertor rest.TableConvertor, replicasPathMapping fieldmanager.ResourcePathMappings) CustomResourceStorage { +func NewStorage(resource schema.GroupResource, singularResource schema.GroupResource, kind, listKind schema.GroupVersionKind, strategy customResourceStrategy, optsGetter generic.RESTOptionsGetter, categories []string, tableConvertor rest.TableConvertor, replicasPathMapping fieldmanager.ResourcePathMappings) CustomResourceStorage { var storage CustomResourceStorage store := &genericregistry.Store{ NewFunc: func() runtime.Object { @@ -56,8 +56,9 @@ func NewStorage(resource schema.GroupResource, kind, listKind schema.GroupVersio ret.SetGroupVersionKind(listKind) return ret }, - PredicateFunc: strategy.MatchCustomResourceDefinitionStorage, - DefaultQualifiedResource: resource, + PredicateFunc: strategy.MatchCustomResourceDefinitionStorage, + DefaultQualifiedResource: resource, + SingularQualifiedResource: singularResource, CreateStrategy: strategy, UpdateStrategy: strategy, diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go index 151f5e6c545..8e920c277a1 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go @@ -93,6 +93,7 @@ func newStorage(t *testing.T) (customresource.CustomResourceStorage, *etcd3testi table, _ := tableconvertor.New(headers) storage := customresource.NewStorage( + groupResource, groupResource, kind, schema.GroupVersionKind{Group: "mygroup.example.com", Version: "v1beta1", Kind: "NoxuItemList"}, diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go index 55a7cbbf8cf..75b1323ca6e 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go @@ -43,10 +43,11 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) (*RES strategy := NewStrategy(scheme) store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &apiextensions.CustomResourceDefinition{} }, - NewListFunc: func() runtime.Object { return &apiextensions.CustomResourceDefinitionList{} }, - PredicateFunc: MatchCustomResourceDefinition, - DefaultQualifiedResource: apiextensions.Resource("customresourcedefinitions"), + NewFunc: func() runtime.Object { return &apiextensions.CustomResourceDefinition{} }, + NewListFunc: func() runtime.Object { return &apiextensions.CustomResourceDefinitionList{} }, + PredicateFunc: MatchCustomResourceDefinition, + DefaultQualifiedResource: apiextensions.Resource("customresourcedefinitions"), + SingularQualifiedResource: apiextensions.Resource("customresourcedefinition"), CreateStrategy: strategy, UpdateStrategy: strategy, @@ -79,13 +80,6 @@ func (r *REST) Categories() []string { return []string{"api-extensions"} } -var _ rest.SingularNameProvider = &REST{} - -// SingularName implements the SingularNameProvider interfaces. This returns singular name of core resource. -func (r *REST) SingularName() string { - return "customresourcedefinition" -} - // Delete adds the CRD finalizer to the list func (r *REST) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) { obj, err := r.Get(ctx, name, &metav1.GetOptions{}) @@ -224,3 +218,9 @@ func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.Updat func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { return r.store.GetResetFields() } + +var _ rest.SingularNameProvider = &StatusREST{} + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go index 9de67ad7a60..b803377631d 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go @@ -372,6 +372,10 @@ func (storage *SimpleRESTStorage) ConvertToTable(ctx context.Context, obj runtim return rest.NewDefaultTableConvertor(schema.GroupResource{Resource: "simple"}).ConvertToTable(ctx, obj, tableOptions) } +func (storate *SimpleRESTStorage) GetSingularName() string { + return "simple" +} + func (storage *SimpleRESTStorage) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { storage.checkContext(ctx) result := &genericapitesting.SimpleList{ @@ -575,6 +579,10 @@ func (s *ConnecterRESTStorage) NewConnectOptions() (runtime.Object, bool, string return s.emptyConnectOptions, false, "" } +func (s *ConnecterRESTStorage) GetSingularName() string { + return "simple" +} + type MetadataRESTStorage struct { *SimpleRESTStorage types []string @@ -619,6 +627,10 @@ type GetWithOptionsRootRESTStorage struct { takesPath string } +func (r *GetWithOptionsRootRESTStorage) GetSingularName() string { + return "simple" +} + func (r *GetWithOptionsRootRESTStorage) NamespaceScoped() bool { return false } @@ -687,6 +699,10 @@ func (storage *SimpleTypedStorage) checkContext(ctx context.Context) { storage.actualNamespace, storage.namespacePresent = request.NamespaceFrom(ctx) } +func (storage *SimpleTypedStorage) GetSingularName() string { + return "simple" +} + func bodyOrDie(response *http.Response) string { defer response.Body.Close() body, err := ioutil.ReadAll(response.Body) @@ -823,6 +839,10 @@ func (UnimplementedRESTStorage) New() runtime.Object { func (UnimplementedRESTStorage) Destroy() { } +func (UnimplementedRESTStorage) GetSingularName() string { + return "" +} + // TestUnimplementedRESTStorage ensures that if a rest.Storage does not implement a given // method, that it is literally not registered with the server. In the past, // we registered everything, and returned method not supported if it didn't support @@ -4289,6 +4309,10 @@ func (storage *SimpleXGSubresourceRESTStorage) GroupVersionKind(containingGV sch return storage.itemGVK } +func (storage *SimpleXGSubresourceRESTStorage) GetSingularName() string { + return "simple" +} + func TestXGSubresource(t *testing.T) { container := restful.NewContainer() container.Router(restful.CurlyRouter{}) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go b/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go index 50c59277539..63d21706209 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go @@ -1080,9 +1080,12 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag if categoriesProvider, ok := storage.(rest.CategoriesProvider); ok { apiResource.Categories = categoriesProvider.Categories() } - if singularNameProvider, ok := storage.(rest.SingularNameProvider); ok { - apiResource.SingularName = singularNameProvider.SingularName() + singularNameProvider, ok := storage.(rest.SingularNameProvider) + if !ok { + return nil, nil, fmt.Errorf("resource %s must implement SingularNameProvider", resource) } + apiResource.SingularName = singularNameProvider.GetSingularName() + if gvkProvider, ok := storage.(rest.GroupVersionKindProvider); ok { gvk := gvkProvider.GroupVersionKind(a.group.GroupVersion) apiResource.Group = gvk.Group diff --git a/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go b/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go index 40bca49665f..6e8d291a3d9 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go @@ -110,6 +110,9 @@ type Store struct { // See qualifiedResourceFromContext for details. DefaultQualifiedResource schema.GroupResource + // SingularQualifiedResource is the singular name of the resource. + SingularQualifiedResource schema.GroupResource + // KeyRootFunc returns the root etcd key for this resource; should not // include trailing "/". This is used for operations that work on the // entire collection (listing and watching). @@ -229,6 +232,8 @@ var _ rest.StandardStorage = &Store{} var _ rest.TableConvertor = &Store{} var _ GenericStore = &Store{} +var _ rest.SingularNameProvider = &Store{} + const ( OptimisticLockErrorMsg = "the object has been modified; please apply your changes to the latest version and try again" resourceCountPollPeriodJitter = 1.2 @@ -1320,6 +1325,12 @@ func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error { if e.DefaultQualifiedResource.Empty() { return fmt.Errorf("store %#v must have a non-empty qualified resource", e) } + if e.SingularQualifiedResource.Empty() { + return fmt.Errorf("store %#v must have a non-empty singular qualified resource", e) + } + if e.DefaultQualifiedResource.Group != e.SingularQualifiedResource.Group { + return fmt.Errorf("store for %#v, singular and plural qualified resource's group name's must match", e) + } if e.NewFunc == nil { return fmt.Errorf("store for %s must have NewFunc set", e.DefaultQualifiedResource.String()) } @@ -1515,6 +1526,10 @@ func (e *Store) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { return e.ResetFieldsStrategy.GetResetFields() } +func (e *Store) GetSingularName() string { + return e.SingularQualifiedResource.Resource +} + // validateIndexers will check the prefix of indexers. func validateIndexers(indexers *cache.Indexers) error { if indexers == nil { diff --git a/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store_test.go b/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store_test.go index f7af4ec89fc..28fe2877cfe 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store_test.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store_test.go @@ -2339,12 +2339,13 @@ func newTestGenericStoreRegistry(t *testing.T, scheme *runtime.Scheme, hasCacheE } return destroyFunc, &Store{ - NewFunc: func() runtime.Object { return &example.Pod{} }, - NewListFunc: func() runtime.Object { return &example.PodList{} }, - DefaultQualifiedResource: example.Resource("pods"), - CreateStrategy: strategy, - UpdateStrategy: strategy, - DeleteStrategy: strategy, + NewFunc: func() runtime.Object { return &example.Pod{} }, + NewListFunc: func() runtime.Object { return &example.PodList{} }, + DefaultQualifiedResource: example.Resource("pods"), + SingularQualifiedResource: example.Resource("pod"), + CreateStrategy: strategy, + UpdateStrategy: strategy, + DeleteStrategy: strategy, KeyRootFunc: func(ctx context.Context) string { return podPrefix }, diff --git a/staging/src/k8s.io/apiserver/pkg/registry/rest/rest.go b/staging/src/k8s.io/apiserver/pkg/registry/rest/rest.go index c55ae9675af..b8d47ff4fe3 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/rest/rest.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/rest/rest.go @@ -92,7 +92,7 @@ type CategoriesProvider interface { // SingularNameProvider returns singular name of resources. This is used by kubectl discovery to have singular // name representation of resources. In case of shortcut conflicts(with CRD shortcuts) singular name should always map to this resource. type SingularNameProvider interface { - SingularName() string + GetSingularName() string } // GroupVersionKindProvider is used to specify a particular GroupVersionKind to discovery. This is used for polymorphic endpoints diff --git a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go index c6b07fc3fff..ccffc8276ce 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go @@ -551,6 +551,10 @@ func (p *testGetterStorage) Get(ctx context.Context, name string, options *metav return nil, nil } +func (p *testGetterStorage) GetSingularName() string { + return "getter" +} + type testNoVerbsStorage struct { Version string } @@ -571,6 +575,10 @@ func (p *testNoVerbsStorage) New() runtime.Object { func (p *testNoVerbsStorage) Destroy() { } +func (p *testNoVerbsStorage) GetSingularName() string { + return "noverb" +} + func fakeVersion() version.Info { return version.Info{ Major: "42", diff --git a/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd/etcd.go b/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd/etcd.go index d20573ed368..624e47b82b2 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd/etcd.go +++ b/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd/etcd.go @@ -41,10 +41,11 @@ type REST struct { func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) *REST { strategy := apiservice.NewStrategy(scheme) store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &apiregistration.APIService{} }, - NewListFunc: func() runtime.Object { return &apiregistration.APIServiceList{} }, - PredicateFunc: apiservice.MatchAPIService, - DefaultQualifiedResource: apiregistration.Resource("apiservices"), + NewFunc: func() runtime.Object { return &apiregistration.APIService{} }, + NewListFunc: func() runtime.Object { return &apiregistration.APIServiceList{} }, + PredicateFunc: apiservice.MatchAPIService, + DefaultQualifiedResource: apiregistration.Resource("apiservices"), + SingularQualifiedResource: apiregistration.Resource("apiservice"), CreateStrategy: strategy, UpdateStrategy: strategy, @@ -169,3 +170,7 @@ func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.Updat func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { return r.store.GetResetFields() } + +func (r *StatusREST) GetSingularName() string { + return r.store.GetSingularName() +} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/fischer/etcd.go b/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/fischer/etcd.go index 4a28fadc5a4..1f49c1b162a 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/fischer/etcd.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/fischer/etcd.go @@ -30,10 +30,11 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) (*reg strategy := NewStrategy(scheme) store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &wardle.Fischer{} }, - NewListFunc: func() runtime.Object { return &wardle.FischerList{} }, - PredicateFunc: MatchFischer, - DefaultQualifiedResource: wardle.Resource("fischers"), + NewFunc: func() runtime.Object { return &wardle.Fischer{} }, + NewListFunc: func() runtime.Object { return &wardle.FischerList{} }, + PredicateFunc: MatchFischer, + DefaultQualifiedResource: wardle.Resource("fischers"), + SingularQualifiedResource: wardle.Resource("fischer"), CreateStrategy: strategy, UpdateStrategy: strategy, diff --git a/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/etcd.go b/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/etcd.go index 271e63cd96a..0179a9221a0 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/etcd.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/etcd.go @@ -30,10 +30,11 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) (*reg strategy := NewStrategy(scheme) store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &wardle.Flunder{} }, - NewListFunc: func() runtime.Object { return &wardle.FlunderList{} }, - PredicateFunc: MatchFlunder, - DefaultQualifiedResource: wardle.Resource("flunders"), + NewFunc: func() runtime.Object { return &wardle.Flunder{} }, + NewListFunc: func() runtime.Object { return &wardle.FlunderList{} }, + PredicateFunc: MatchFlunder, + DefaultQualifiedResource: wardle.Resource("flunders"), + SingularQualifiedResource: wardle.Resource("flunder"), CreateStrategy: strategy, UpdateStrategy: strategy,