From ab376e09dd505d22886bde31f8173b3bcd22dff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Wed, 2 Nov 2022 12:50:24 +0300 Subject: [PATCH 01/10] Add integration tests for shortnames expanding to correct resources This adds new integration tests to test shortnames and singular names are expanding to correct resources. In this case, core types have always higher precendence than CRDs. --- test/cmd/discovery.sh | 145 ++++++++++++++++++++++++++++++++++++++ test/cmd/legacy-script.sh | 6 ++ 2 files changed, 151 insertions(+) diff --git a/test/cmd/discovery.sh b/test/cmd/discovery.sh index 035cdc10e6b..4308d9d216b 100755 --- a/test/cmd/discovery.sh +++ b/test/cmd/discovery.sh @@ -57,6 +57,151 @@ run_assert_short_name_tests() { ## test if a short name is exported during discovery kube::test::if_has_string "${output_message}" '{"name":"configmaps","singularName":"","namespaced":true,"kind":"ConfigMap","verbs":\["create","delete","deletecollection","get","list","patch","update","watch"\],"shortNames":\["cm"\],"storageVersionHash":' + # check that there is no pod with the name test-crd-example + output_message=$(kubectl get pod) + kube::test::if_has_not_string "${output_message}" "test-crd-example" + + kubectl create -f - << __EOF__ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: examples.test.com +spec: + group: test.com + scope: Namespaced + versions: + - name: v1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + test: + type: string + names: + plural: examples + singular: example + shortNames: + - pod + kind: Example +__EOF__ + + # Test that we can list this new custom resource + kube::test::wait_object_assert customresourcedefinitions "{{range.items}}{{if eq $id_field \\\"examples.test.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'examples.test.com:' + + kubectl create -f - << __EOF__ +apiVersion: test.com/v1 +kind: Example +metadata: + name: test-crd-example +spec: + test: test +__EOF__ + + # Test that we can list this new custom resource + kube::test::wait_object_assert examples "{{range.items}}{{${id_field:?}}}:{{end}}" 'test-crd-example:' + + output_message=$(kubectl get examples) + kube::test::if_has_string "${output_message}" "test-crd-example" + + # test that get pod returns v1/pod instead crd + output_message=$(kubectl get pod) + kube::test::if_has_not_string "${output_message}" "test-crd-example" + + # invalidate cache and assure that still correct resource is shown + kubectl api-resources + + # retest the above cases after invalidating cache + output_message=$(kubectl get examples) + kube::test::if_has_string "${output_message}" "test-crd-example" + + output_message=$(kubectl get pod) + kube::test::if_has_not_string "${output_message}" "test-crd-example" + + # Cleanup + kubectl delete examples/test-crd-example + kubectl delete customresourcedefinition examples.test.com + + set +o nounset + set +o errexit +} + +run_assert_singular_name_tests() { + set -o nounset + set -o errexit + + create_and_use_new_namespace + kube::log::status "Testing assert singular name" + + # check that there is no pod with the name test-crd-example + output_message=$(kubectl get pod) + kube::test::if_has_not_string "${output_message}" "test-crd-example" + + kubectl create -f - << __EOF__ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: examples.test.com +spec: + group: test.com + scope: Namespaced + versions: + - name: v1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + test: + type: string + names: + plural: examples + singular: pod + kind: Example +__EOF__ + + # Test that we can list this new custom resource + kube::test::wait_object_assert customresourcedefinitions "{{range.items}}{{if eq $id_field \\\"examples.test.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'examples.test.com:' + + kubectl create -f - << __EOF__ +apiVersion: test.com/v1 +kind: Example +metadata: + name: test-crd-example +spec: + test: test +__EOF__ + + # Test that we can list this new custom resource + kube::test::wait_object_assert examples "{{range.items}}{{${id_field:?}}}:{{end}}" 'test-crd-example:' + + output_message=$(kubectl get examples) + kube::test::if_has_string "${output_message}" "test-crd-example" + + output_message=$(kubectl get pod) + kube::test::if_has_not_string "${output_message}" "test-crd-example" + + # invalidate cache and assure that still correct resource is shown + kubectl api-resources + + output_message=$(kubectl get examples) + kube::test::if_has_string "${output_message}" "test-crd-example" + + output_message=$(kubectl get pod) + kube::test::if_has_not_string "${output_message}" "test-crd-example" + + # Cleanup + kubectl delete examples/test-crd-example + kubectl delete customresourcedefinition examples.test.com + set +o nounset set +o errexit } diff --git a/test/cmd/legacy-script.sh b/test/cmd/legacy-script.sh index 6fff7b11ae9..5339b1512d2 100755 --- a/test/cmd/legacy-script.sh +++ b/test/cmd/legacy-script.sh @@ -505,6 +505,12 @@ runTests() { record_command run_assert_short_name_tests + ######################### + # Assert singular name # + ######################### + + record_command run_assert_singular_name_tests + ######################### # Assert categories # ######################### From 0990ba1cc92449bbbd9b25a4391f1da834f8c5fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Wed, 2 Nov 2022 12:53:56 +0300 Subject: [PATCH 02/10] Introduce singularNameProvider for core types This introduces `singularNameProvider`. This provider will be used by core types to have their singular names are defined in discovery endpoint. Thanks to that, core resources singular name always have higher precedence than CRDs shortcuts or singular names. --- .../apps/daemonset/storage/storage.go | 7 +++++ .../apps/daemonset/storage/storage_test.go | 8 +++++ .../apps/deployment/storage/storage.go | 7 +++++ .../apps/deployment/storage/storage_test.go | 8 +++++ .../apps/replicaset/storage/storage.go | 7 +++++ .../apps/replicaset/storage/storage_test.go | 8 +++++ .../apps/statefulset/storage/storage.go | 7 +++++ .../apps/statefulset/storage/storage_test.go | 8 +++++ .../storage/storage.go | 7 +++++ .../storage/storage_test.go | 8 +++++ pkg/registry/batch/cronjob/storage/storage.go | 7 +++++ pkg/registry/batch/job/storage/storage.go | 7 +++++ .../batch/job/storage/storage_test.go | 8 +++++ .../certificates/storage/storage.go | 7 +++++ .../coordination/lease/storage/storage.go | 8 +++++ .../core/configmap/storage/storage.go | 7 +++++ .../core/configmap/storage/storage_test.go | 8 +++++ pkg/registry/core/endpoint/storage/storage.go | 7 +++++ pkg/registry/core/event/storage/storage.go | 7 +++++ .../core/event/storage/storage_test.go | 8 +++++ .../core/limitrange/storage/storage.go | 7 +++++ .../core/limitrange/storage/storage_test.go | 8 +++++ .../core/namespace/storage/storage.go | 7 +++++ .../core/namespace/storage/storage_test.go | 8 +++++ pkg/registry/core/node/storage/storage.go | 10 +++++++ .../core/persistentvolume/storage/storage.go | 7 +++++ .../persistentvolume/storage/storage_test.go | 8 +++++ .../persistentvolumeclaim/storage/storage.go | 7 +++++ .../storage/storage_test.go | 8 +++++ pkg/registry/core/pod/storage/storage.go | 7 +++++ pkg/registry/core/pod/storage/storage_test.go | 8 +++++ .../core/podtemplate/storage/storage.go | 8 +++++ .../core/podtemplate/storage/storage_test.go | 8 +++++ .../replicationcontroller/storage/storage.go | 7 +++++ .../storage/storage_test.go | 8 +++++ .../core/resourcequota/storage/storage.go | 7 +++++ .../resourcequota/storage/storage_test.go | 8 +++++ pkg/registry/core/secret/storage/storage.go | 8 +++++ .../core/secret/storage/storage_test.go | 8 +++++ pkg/registry/core/service/storage/storage.go | 7 +++++ .../core/service/storage/storage_test.go | 8 +++++ .../core/serviceaccount/storage/storage.go | 7 +++++ .../serviceaccount/storage/storage_test.go | 8 +++++ .../endpointslice/storage/storage.go | 8 +++++ .../networking/ingress/storage/storage.go | 7 +++++ .../ingress/storage/storage_test.go | 8 +++++ .../ingressclass/storage/storage.go | 8 +++++ .../networkpolicy/storage/storage.go | 7 +++++ .../networkpolicy/storage/storage_test.go | 8 +++++ .../poddisruptionbudget/storage/storage.go | 7 +++++ .../rbac/clusterrole/storage/storage.go | 7 +++++ .../clusterrolebinding/storage/storage.go | 8 +++++ pkg/registry/rbac/role/storage/storage.go | 7 +++++ .../rbac/rolebinding/storage/storage.go | 8 +++++ .../registrytest/singularNameProvider.go | 30 +++++++++++++++++++ .../priorityclass/storage/storage.go | 7 +++++ .../priorityclass/storage/storage_test.go | 8 +++++ .../storage/storageclass/storage/storage.go | 7 +++++ .../storageclass/storage/storage_test.go | 8 +++++ .../volumeattachment/storage/storage.go | 7 +++++ .../volumeattachment/storage/storage_test.go | 8 +++++ .../registry/customresourcedefinition/etcd.go | 7 +++++ .../apiserver/pkg/endpoints/installer.go | 3 ++ .../apiserver/pkg/registry/rest/rest.go | 6 ++++ test/cmd/discovery.sh | 2 +- 65 files changed, 501 insertions(+), 1 deletion(-) create mode 100644 pkg/registry/registrytest/singularNameProvider.go diff --git a/pkg/registry/apps/daemonset/storage/storage.go b/pkg/registry/apps/daemonset/storage/storage.go index 84df2450283..c40ac6fc36d 100644 --- a/pkg/registry/apps/daemonset/storage/storage.go +++ b/pkg/registry/apps/daemonset/storage/storage.go @@ -78,6 +78,13 @@ 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 diff --git a/pkg/registry/apps/daemonset/storage/storage_test.go b/pkg/registry/apps/daemonset/storage/storage_test.go index eaf15ffcdae..fcd06c180dd 100644 --- a/pkg/registry/apps/daemonset/storage/storage_test.go +++ b/pkg/registry/apps/daemonset/storage/storage_test.go @@ -197,4 +197,12 @@ 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 8b05dd0b663..3da212d0974 100644 --- a/pkg/registry/apps/deployment/storage/storage.go +++ b/pkg/registry/apps/deployment/storage/storage.go @@ -130,6 +130,13 @@ 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 diff --git a/pkg/registry/apps/deployment/storage/storage_test.go b/pkg/registry/apps/deployment/storage/storage_test.go index d7b371040d2..05b14b0b45e 100644 --- a/pkg/registry/apps/deployment/storage/storage_test.go +++ b/pkg/registry/apps/deployment/storage/storage_test.go @@ -455,6 +455,14 @@ 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 0c467d37327..97592c1d770 100644 --- a/pkg/registry/apps/replicaset/storage/storage.go +++ b/pkg/registry/apps/replicaset/storage/storage.go @@ -126,6 +126,13 @@ 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 diff --git a/pkg/registry/apps/replicaset/storage/storage_test.go b/pkg/registry/apps/replicaset/storage/storage_test.go index 392c1f95b21..d6223bbe849 100644 --- a/pkg/registry/apps/replicaset/storage/storage_test.go +++ b/pkg/registry/apps/replicaset/storage/storage_test.go @@ -399,6 +399,14 @@ 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 47558534cdd..cf834362f9f 100644 --- a/pkg/registry/apps/statefulset/storage/storage.go +++ b/pkg/registry/apps/statefulset/storage/storage.go @@ -114,6 +114,13 @@ 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 diff --git a/pkg/registry/apps/statefulset/storage/storage_test.go b/pkg/registry/apps/statefulset/storage/storage_test.go index cdce909bd77..649ffffed15 100644 --- a/pkg/registry/apps/statefulset/storage/storage_test.go +++ b/pkg/registry/apps/statefulset/storage/storage_test.go @@ -199,6 +199,14 @@ 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/autoscaling/horizontalpodautoscaler/storage/storage.go b/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go index 03171ed1ff0..44a7911eea3 100644 --- a/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go +++ b/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go @@ -78,6 +78,13 @@ 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 diff --git a/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage_test.go b/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage_test.go index 589932db37f..bf269222cd9 100644 --- a/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage_test.go +++ b/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage_test.go @@ -176,6 +176,14 @@ 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 637dc8f3754..51d453bfe74 100644 --- a/pkg/registry/batch/cronjob/storage/storage.go +++ b/pkg/registry/batch/cronjob/storage/storage.go @@ -76,6 +76,13 @@ 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 diff --git a/pkg/registry/batch/job/storage/storage.go b/pkg/registry/batch/job/storage/storage.go index f6cfa679536..93c6eb8b606 100644 --- a/pkg/registry/batch/job/storage/storage.go +++ b/pkg/registry/batch/job/storage/storage.go @@ -96,6 +96,13 @@ 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 diff --git a/pkg/registry/batch/job/storage/storage_test.go b/pkg/registry/batch/job/storage/storage_test.go index 765b3179509..5b9b991f61c 100644 --- a/pkg/registry/batch/job/storage/storage_test.go +++ b/pkg/registry/batch/job/storage/storage_test.go @@ -375,3 +375,11 @@ 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 8de7828efde..5c72cc2be68 100644 --- a/pkg/registry/certificates/certificates/storage/storage.go +++ b/pkg/registry/certificates/certificates/storage/storage.go @@ -79,6 +79,13 @@ 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 diff --git a/pkg/registry/coordination/lease/storage/storage.go b/pkg/registry/coordination/lease/storage/storage.go index 8989a293a6d..a0f67bc2ff4 100644 --- a/pkg/registry/coordination/lease/storage/storage.go +++ b/pkg/registry/coordination/lease/storage/storage.go @@ -20,6 +20,7 @@ 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" @@ -52,3 +53,10 @@ 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/configmap/storage/storage.go b/pkg/registry/core/configmap/storage/storage.go index 8180c56e830..47648ded842 100644 --- a/pkg/registry/core/configmap/storage/storage.go +++ b/pkg/registry/core/configmap/storage/storage.go @@ -66,3 +66,10 @@ 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 04ccc8d8999..78b927d4586 100644 --- a/pkg/registry/core/configmap/storage/storage_test.go +++ b/pkg/registry/core/configmap/storage/storage_test.go @@ -172,3 +172,11 @@ 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 ff082994cea..e0f36f29e73 100644 --- a/pkg/registry/core/endpoint/storage/storage.go +++ b/pkg/registry/core/endpoint/storage/storage.go @@ -60,3 +60,10 @@ 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 ee4498934d1..7be63d0ce60 100644 --- a/pkg/registry/core/event/storage/storage.go +++ b/pkg/registry/core/event/storage/storage.go @@ -64,3 +64,10 @@ 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 134de72b8bf..854c7776050 100644 --- a/pkg/registry/core/event/storage/storage_test.go +++ b/pkg/registry/core/event/storage/storage_test.go @@ -123,3 +123,11 @@ 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 b3fd401f701..b286f7f9230 100644 --- a/pkg/registry/core/limitrange/storage/storage.go +++ b/pkg/registry/core/limitrange/storage/storage.go @@ -58,3 +58,10 @@ 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 3bbcad7f5e3..38b16a3b7d0 100644 --- a/pkg/registry/core/limitrange/storage/storage_test.go +++ b/pkg/registry/core/limitrange/storage/storage_test.go @@ -171,3 +171,11 @@ 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 37b130092ca..3201ca45498 100644 --- a/pkg/registry/core/namespace/storage/storage.go +++ b/pkg/registry/core/namespace/storage/storage.go @@ -291,6 +291,13 @@ 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 { diff --git a/pkg/registry/core/namespace/storage/storage_test.go b/pkg/registry/core/namespace/storage/storage_test.go index a1bfd9e9af8..e94c9b3fb33 100644 --- a/pkg/registry/core/namespace/storage/storage_test.go +++ b/pkg/registry/core/namespace/storage/storage_test.go @@ -628,3 +628,11 @@ 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/storage/storage.go b/pkg/registry/core/node/storage/storage.go index 56e806770f4..e8ecf8b9fe4 100644 --- a/pkg/registry/core/node/storage/storage.go +++ b/pkg/registry/core/node/storage/storage.go @@ -167,7 +167,17 @@ func (r *REST) ResourceLocation(ctx context.Context, id string) (*url.URL, http. return node.ResourceLocation(r, r.connection, r.proxyTransport, ctx, id) } +// Implement ShortNamesProvider +var _ rest.ShortNamesProvider = &REST{} + // ShortNames implements the ShortNamesProvider interface. Returns a list of short names for a resource. 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 df65eabc879..06bd7beeb4c 100644 --- a/pkg/registry/core/persistentvolume/storage/storage.go +++ b/pkg/registry/core/persistentvolume/storage/storage.go @@ -73,6 +73,13 @@ 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 diff --git a/pkg/registry/core/persistentvolume/storage/storage_test.go b/pkg/registry/core/persistentvolume/storage/storage_test.go index c03fa3248a9..5c8a7b5bdce 100644 --- a/pkg/registry/core/persistentvolume/storage/storage_test.go +++ b/pkg/registry/core/persistentvolume/storage/storage_test.go @@ -208,3 +208,11 @@ 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 d472bbd8ef3..26e6d80c867 100644 --- a/pkg/registry/core/persistentvolumeclaim/storage/storage.go +++ b/pkg/registry/core/persistentvolumeclaim/storage/storage.go @@ -77,6 +77,13 @@ 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. diff --git a/pkg/registry/core/persistentvolumeclaim/storage/storage_test.go b/pkg/registry/core/persistentvolumeclaim/storage/storage_test.go index 54c0ca625f5..d94fed0fcfe 100644 --- a/pkg/registry/core/persistentvolumeclaim/storage/storage_test.go +++ b/pkg/registry/core/persistentvolumeclaim/storage/storage_test.go @@ -212,6 +212,14 @@ 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/storage/storage.go b/pkg/registry/core/pod/storage/storage.go index 3960918de62..034884960d9 100644 --- a/pkg/registry/core/pod/storage/storage.go +++ b/pkg/registry/core/pod/storage/storage.go @@ -142,6 +142,13 @@ 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 diff --git a/pkg/registry/core/pod/storage/storage_test.go b/pkg/registry/core/pod/storage/storage_test.go index 1e15ca8a834..dc7160078c4 100644 --- a/pkg/registry/core/pod/storage/storage_test.go +++ b/pkg/registry/core/pod/storage/storage_test.go @@ -1274,3 +1274,11 @@ 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 d7dca23868a..66d267d6777 100644 --- a/pkg/registry/core/podtemplate/storage/storage.go +++ b/pkg/registry/core/podtemplate/storage/storage.go @@ -20,6 +20,7 @@ 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" @@ -53,3 +54,10 @@ 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 785fc6fcb62..59c3413f902 100644 --- a/pkg/registry/core/podtemplate/storage/storage_test.go +++ b/pkg/registry/core/podtemplate/storage/storage_test.go @@ -153,3 +153,11 @@ 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 39a59f4a73e..d5fca9c0f96 100644 --- a/pkg/registry/core/replicationcontroller/storage/storage.go +++ b/pkg/registry/core/replicationcontroller/storage/storage.go @@ -122,6 +122,13 @@ 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 diff --git a/pkg/registry/core/replicationcontroller/storage/storage_test.go b/pkg/registry/core/replicationcontroller/storage/storage_test.go index 009fed33b1a..60e133cb26a 100644 --- a/pkg/registry/core/replicationcontroller/storage/storage_test.go +++ b/pkg/registry/core/replicationcontroller/storage/storage_test.go @@ -352,6 +352,14 @@ 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 d438ec792e2..76b71dd2096 100644 --- a/pkg/registry/core/resourcequota/storage/storage.go +++ b/pkg/registry/core/resourcequota/storage/storage.go @@ -72,6 +72,13 @@ 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 diff --git a/pkg/registry/core/resourcequota/storage/storage_test.go b/pkg/registry/core/resourcequota/storage/storage_test.go index 9b750553f83..8459c32bf7f 100644 --- a/pkg/registry/core/resourcequota/storage/storage_test.go +++ b/pkg/registry/core/resourcequota/storage/storage_test.go @@ -217,3 +217,11 @@ 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 81e2892df57..b02cb83546c 100644 --- a/pkg/registry/core/secret/storage/storage.go +++ b/pkg/registry/core/secret/storage/storage.go @@ -20,6 +20,7 @@ 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" @@ -57,3 +58,10 @@ 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 a3850a2dafe..68bc7dcb5fb 100644 --- a/pkg/registry/core/secret/storage/storage_test.go +++ b/pkg/registry/core/secret/storage/storage_test.go @@ -143,3 +143,11 @@ 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/storage/storage.go b/pkg/registry/core/service/storage/storage.go index 4ee5428e819..172135ed88e 100644 --- a/pkg/registry/core/service/storage/storage.go +++ b/pkg/registry/core/service/storage/storage.go @@ -153,6 +153,13 @@ 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() diff --git a/pkg/registry/core/service/storage/storage_test.go b/pkg/registry/core/service/storage/storage_test.go index 1345ed519fa..1cb514132df 100644 --- a/pkg/registry/core/service/storage/storage_test.go +++ b/pkg/registry/core/service/storage/storage_test.go @@ -279,6 +279,14 @@ 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 60f83b74133..d44573bf607 100644 --- a/pkg/registry/core/serviceaccount/storage/storage.go +++ b/pkg/registry/core/serviceaccount/storage/storage.go @@ -84,3 +84,10 @@ 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 220f5053047..dfaaa30b315 100644 --- a/pkg/registry/core/serviceaccount/storage/storage_test.go +++ b/pkg/registry/core/serviceaccount/storage/storage_test.go @@ -146,3 +146,11 @@ 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/discovery/endpointslice/storage/storage.go b/pkg/registry/discovery/endpointslice/storage/storage.go index 756553ad580..d8b4d1b9113 100644 --- a/pkg/registry/discovery/endpointslice/storage/storage.go +++ b/pkg/registry/discovery/endpointslice/storage/storage.go @@ -20,6 +20,7 @@ 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" @@ -51,3 +52,10 @@ 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/networking/ingress/storage/storage.go b/pkg/registry/networking/ingress/storage/storage.go index 71ab37c455e..dd82551cb1d 100644 --- a/pkg/registry/networking/ingress/storage/storage.go +++ b/pkg/registry/networking/ingress/storage/storage.go @@ -70,6 +70,13 @@ 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 diff --git a/pkg/registry/networking/ingress/storage/storage_test.go b/pkg/registry/networking/ingress/storage/storage_test.go index 28c42ea1c48..199ea5002e9 100644 --- a/pkg/registry/networking/ingress/storage/storage_test.go +++ b/pkg/registry/networking/ingress/storage/storage_test.go @@ -250,4 +250,12 @@ 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 187c7317cba..889b7398011 100644 --- a/pkg/registry/networking/ingressclass/storage/storage.go +++ b/pkg/registry/networking/ingressclass/storage/storage.go @@ -20,6 +20,7 @@ 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" @@ -52,3 +53,10 @@ 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 0101077b662..8f2ed82fc16 100644 --- a/pkg/registry/networking/networkpolicy/storage/storage.go +++ b/pkg/registry/networking/networkpolicy/storage/storage.go @@ -72,6 +72,13 @@ 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 diff --git a/pkg/registry/networking/networkpolicy/storage/storage_test.go b/pkg/registry/networking/networkpolicy/storage/storage_test.go index 15ab8780910..57685615099 100644 --- a/pkg/registry/networking/networkpolicy/storage/storage_test.go +++ b/pkg/registry/networking/networkpolicy/storage/storage_test.go @@ -198,6 +198,14 @@ 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/policy/poddisruptionbudget/storage/storage.go b/pkg/registry/policy/poddisruptionbudget/storage/storage.go index 4af2ea2429f..55fb2e360f6 100644 --- a/pkg/registry/policy/poddisruptionbudget/storage/storage.go +++ b/pkg/registry/policy/poddisruptionbudget/storage/storage.go @@ -67,6 +67,13 @@ 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 diff --git a/pkg/registry/rbac/clusterrole/storage/storage.go b/pkg/registry/rbac/clusterrole/storage/storage.go index 59347f767a4..aa04dd376b4 100644 --- a/pkg/registry/rbac/clusterrole/storage/storage.go +++ b/pkg/registry/rbac/clusterrole/storage/storage.go @@ -51,3 +51,10 @@ 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/storage/storage.go b/pkg/registry/rbac/clusterrolebinding/storage/storage.go index 762730788b6..7d662fd726a 100644 --- a/pkg/registry/rbac/clusterrolebinding/storage/storage.go +++ b/pkg/registry/rbac/clusterrolebinding/storage/storage.go @@ -20,6 +20,7 @@ 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" @@ -52,3 +53,10 @@ 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/storage/storage.go b/pkg/registry/rbac/role/storage/storage.go index 6e6700ede98..1eb312c12bf 100644 --- a/pkg/registry/rbac/role/storage/storage.go +++ b/pkg/registry/rbac/role/storage/storage.go @@ -51,3 +51,10 @@ 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/storage/storage.go b/pkg/registry/rbac/rolebinding/storage/storage.go index 0cbcfa0f644..8a6ee171a3d 100644 --- a/pkg/registry/rbac/rolebinding/storage/storage.go +++ b/pkg/registry/rbac/rolebinding/storage/storage.go @@ -20,6 +20,7 @@ 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" @@ -52,3 +53,10 @@ 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 new file mode 100644 index 00000000000..5056b0dd477 --- /dev/null +++ b/pkg/registry/registrytest/singularNameProvider.go @@ -0,0 +1,30 @@ +/* +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 b84a573a12e..b2e78035b19 100644 --- a/pkg/registry/scheduling/priorityclass/storage/storage.go +++ b/pkg/registry/scheduling/priorityclass/storage/storage.go @@ -67,6 +67,13 @@ 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 de6eba80999..a0a0ae65de0 100644 --- a/pkg/registry/scheduling/priorityclass/storage/storage_test.go +++ b/pkg/registry/scheduling/priorityclass/storage/storage_test.go @@ -179,3 +179,11 @@ 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/storageclass/storage/storage.go b/pkg/registry/storage/storageclass/storage/storage.go index fb4394e6641..fbac3a484ef 100644 --- a/pkg/registry/storage/storageclass/storage/storage.go +++ b/pkg/registry/storage/storageclass/storage/storage.go @@ -62,3 +62,10 @@ 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 fb1a20dba23..8196e5225dd 100644 --- a/pkg/registry/storage/storageclass/storage/storage_test.go +++ b/pkg/registry/storage/storageclass/storage/storage_test.go @@ -160,3 +160,11 @@ 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 91c1c2a1142..e82338fbd7f 100644 --- a/pkg/registry/storage/volumeattachment/storage/storage.go +++ b/pkg/registry/storage/volumeattachment/storage/storage.go @@ -73,6 +73,13 @@ 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 diff --git a/pkg/registry/storage/volumeattachment/storage/storage_test.go b/pkg/registry/storage/volumeattachment/storage/storage_test.go index 6ff5c9f749a..22c13985fed 100644 --- a/pkg/registry/storage/volumeattachment/storage/storage_test.go +++ b/pkg/registry/storage/volumeattachment/storage/storage_test.go @@ -200,3 +200,11 @@ 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/registry/customresourcedefinition/etcd.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go index 2523076edf9..55a7cbbf8cf 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 @@ -79,6 +79,13 @@ 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{}) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go b/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go index b0af449f09b..50c59277539 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go @@ -1080,6 +1080,9 @@ 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() + } 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/rest/rest.go b/staging/src/k8s.io/apiserver/pkg/registry/rest/rest.go index 6330ea8f531..c55ae9675af 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/rest/rest.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/rest/rest.go @@ -89,6 +89,12 @@ type CategoriesProvider interface { Categories() []string } +// 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 +} + // GroupVersionKindProvider is used to specify a particular GroupVersionKind to discovery. This is used for polymorphic endpoints // which generally point to foreign versions. Scale refers to Scale.v1beta1.extensions for instance. // This trumps KindProvider since it is capable of providing the information required. diff --git a/test/cmd/discovery.sh b/test/cmd/discovery.sh index 4308d9d216b..56aa7859fb1 100755 --- a/test/cmd/discovery.sh +++ b/test/cmd/discovery.sh @@ -55,7 +55,7 @@ run_assert_short_name_tests() { output_message=$(kubectl get --raw=/api/v1) ## test if a short name is exported during discovery - kube::test::if_has_string "${output_message}" '{"name":"configmaps","singularName":"","namespaced":true,"kind":"ConfigMap","verbs":\["create","delete","deletecollection","get","list","patch","update","watch"\],"shortNames":\["cm"\],"storageVersionHash":' + kube::test::if_has_string "${output_message}" '{"name":"configmaps","singularName":"configmap","namespaced":true,"kind":"ConfigMap","verbs":\["create","delete","deletecollection","get","list","patch","update","watch"\],"shortNames":\["cm"\],"storageVersionHash":' # check that there is no pod with the name test-crd-example output_message=$(kubectl get pod) From d6532f5eb868aa21e23109c300958d42f8c0d797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Wed, 2 Nov 2022 15:11:08 +0300 Subject: [PATCH 03/10] run discovery tests if resources are supported --- test/cmd/discovery.sh | 6 +++--- test/cmd/legacy-script.sh | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/test/cmd/discovery.sh b/test/cmd/discovery.sh index 56aa7859fb1..daec7052202 100755 --- a/test/cmd/discovery.sh +++ b/test/cmd/discovery.sh @@ -91,7 +91,7 @@ spec: __EOF__ # Test that we can list this new custom resource - kube::test::wait_object_assert customresourcedefinitions "{{range.items}}{{if eq $id_field \\\"examples.test.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'examples.test.com:' + kube::test::wait_object_assert customresourcedefinitions "{{range.items}}{{if eq ${id_field:?} \\\"examples.test.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'examples.test.com:' kubectl create -f - << __EOF__ apiVersion: test.com/v1 @@ -169,7 +169,7 @@ spec: __EOF__ # Test that we can list this new custom resource - kube::test::wait_object_assert customresourcedefinitions "{{range.items}}{{if eq $id_field \\\"examples.test.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'examples.test.com:' + kube::test::wait_object_assert customresourcedefinitions "{{range.items}}{{if eq ${id_field:?} \\\"examples.test.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'examples.test.com:' kubectl create -f - << __EOF__ apiVersion: test.com/v1 @@ -181,7 +181,7 @@ spec: __EOF__ # Test that we can list this new custom resource - kube::test::wait_object_assert examples "{{range.items}}{{${id_field:?}}}:{{end}}" 'test-crd-example:' + kube::test::wait_object_assert examples "{{range.items}}{{$id_field}}:{{end}}" 'test-crd-example:' output_message=$(kubectl get examples) kube::test::if_has_string "${output_message}" "test-crd-example" diff --git a/test/cmd/legacy-script.sh b/test/cmd/legacy-script.sh index 5339b1512d2..5e832df259a 100755 --- a/test/cmd/legacy-script.sh +++ b/test/cmd/legacy-script.sh @@ -503,13 +503,17 @@ runTests() { # Assert short name # ######################### - record_command run_assert_short_name_tests + if kube::test::if_supports_resource "${customresourcedefinitions}" && kube::test::if_supports_resource "${pods}" && kube::test::if_supports_resource "${configmaps}" ; then + record_command run_assert_short_name_tests + fi ######################### # Assert singular name # ######################### - record_command run_assert_singular_name_tests + if kube::test::if_supports_resource "${customresourcedefinitions}" && kube::test::if_supports_resource "${pods}" ; then + record_command run_assert_singular_name_tests + fi ######################### # Assert categories # From 578ddde80e72a300fdb3798d68e550d2b4a61203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Thu, 3 Nov 2022 10:18:45 +0300 Subject: [PATCH 04/10] Add singular name for the rest of types --- .../storage/storage.go | 3 +- .../storage/storage.go | 3 +- .../storageversion/storage/storage.go | 9 ++++- .../controllerrevision/storage/storage.go | 7 ++-- .../apps/daemonset/storage/storage.go | 20 +++++----- .../apps/daemonset/storage/storage_test.go | 8 ---- .../apps/deployment/storage/storage.go | 32 ++++++++++----- .../apps/deployment/storage/storage_test.go | 8 ---- .../apps/replicaset/storage/storage.go | 28 ++++++++----- .../apps/replicaset/storage/storage_test.go | 8 ---- .../apps/statefulset/storage/storage.go | 26 +++++++----- .../apps/statefulset/storage/storage_test.go | 8 ---- .../authentication/tokenreview/storage.go | 6 +++ .../localsubjectaccessreview/rest.go | 6 +++ .../selfsubjectaccessreview/rest.go | 6 +++ .../selfsubjectrulesreview/rest.go | 6 +++ .../authorization/subjectaccessreview/rest.go | 6 +++ .../storage/storage.go | 20 +++++----- .../storage/storage_test.go | 8 ---- pkg/registry/batch/cronjob/storage/storage.go | 20 +++++----- pkg/registry/batch/job/storage/storage.go | 22 +++++----- .../batch/job/storage/storage_test.go | 8 ---- .../certificates/storage/storage.go | 26 +++++++----- .../coordination/lease/storage/storage.go | 15 ++----- pkg/registry/core/componentstatus/rest.go | 6 +++ .../core/configmap/storage/storage.go | 16 +++----- .../core/configmap/storage/storage_test.go | 8 ---- pkg/registry/core/endpoint/storage/storage.go | 14 ++----- pkg/registry/core/event/storage/storage.go | 10 +---- .../core/event/storage/storage_test.go | 8 ---- .../core/limitrange/storage/storage.go | 14 ++----- .../core/limitrange/storage/storage_test.go | 8 ---- .../core/namespace/storage/storage.go | 34 +++++++++++----- .../core/namespace/storage/storage_test.go | 8 ---- pkg/registry/core/node/rest/proxy.go | 6 +++ pkg/registry/core/node/storage/storage.go | 22 +++++----- .../core/persistentvolume/storage/storage.go | 22 +++++----- .../persistentvolume/storage/storage_test.go | 8 ---- .../persistentvolumeclaim/storage/storage.go | 22 +++++----- .../storage/storage_test.go | 8 ---- pkg/registry/core/pod/rest/log.go | 6 +++ pkg/registry/core/pod/rest/subresources.go | 24 +++++++++++ pkg/registry/core/pod/storage/eviction.go | 6 +++ pkg/registry/core/pod/storage/storage.go | 40 ++++++++++++++----- pkg/registry/core/pod/storage/storage_test.go | 8 ---- .../core/podtemplate/storage/storage.go | 15 ++----- .../core/podtemplate/storage/storage_test.go | 8 ---- .../replicationcontroller/storage/storage.go | 28 ++++++++----- .../storage/storage_test.go | 8 ---- .../core/resourcequota/storage/storage.go | 20 +++++----- .../resourcequota/storage/storage_test.go | 8 ---- pkg/registry/core/secret/storage/storage.go | 17 +++----- .../core/secret/storage/storage_test.go | 8 ---- pkg/registry/core/service/proxy.go | 6 +++ pkg/registry/core/service/storage/storage.go | 22 +++++----- .../core/service/storage/storage_test.go | 8 ---- .../core/serviceaccount/storage/storage.go | 14 ++----- .../serviceaccount/storage/storage_test.go | 8 ---- .../core/serviceaccount/storage/token.go | 6 +++ .../endpointslice/storage/storage.go | 15 ++----- .../flowcontrol/flowschema/storage/storage.go | 13 ++++-- .../storage/storage.go | 13 ++++-- .../networking/clustercidr/storage/storage.go | 7 ++-- .../networking/ingress/storage/storage.go | 20 +++++----- .../ingress/storage/storage_test.go | 8 ---- .../ingressclass/storage/storage.go | 15 ++----- .../networkpolicy/storage/storage.go | 20 +++++----- .../networkpolicy/storage/storage_test.go | 8 ---- .../node/runtimeclass/storage/storage.go | 3 +- .../poddisruptionbudget/storage/storage.go | 20 +++++----- .../podsecuritypolicy/storage/storage.go | 7 ++-- .../rbac/clusterrole/policybased/storage.go | 6 +++ .../rbac/clusterrole/storage/storage.go | 14 ++----- .../clusterrolebinding/policybased/storage.go | 6 +++ .../clusterrolebinding/storage/storage.go | 15 ++----- pkg/registry/rbac/role/policybased/storage.go | 6 +++ pkg/registry/rbac/role/storage/storage.go | 14 ++----- .../rbac/rolebinding/policybased/storage.go | 6 +++ .../rbac/rolebinding/storage/storage.go | 15 ++----- .../registrytest/singularNameProvider.go | 30 -------------- .../priorityclass/storage/storage.go | 14 ++----- .../priorityclass/storage/storage_test.go | 8 ---- .../storage/csidriver/storage/storage.go | 7 ++-- .../storage/csinode/storage/storage.go | 7 ++-- .../csistoragecapacity/storage/storage.go | 7 ++-- .../storage/storageclass/storage/storage.go | 14 ++----- .../storageclass/storage/storage_test.go | 8 ---- .../volumeattachment/storage/storage.go | 20 +++++----- .../volumeattachment/storage/storage_test.go | 8 ---- .../pkg/apiserver/customresource_handler.go | 2 + .../pkg/registry/customresource/etcd.go | 7 ++-- .../pkg/registry/customresource/etcd_test.go | 1 + .../registry/customresourcedefinition/etcd.go | 22 +++++----- .../apiserver/pkg/endpoints/apiserver_test.go | 24 +++++++++++ .../apiserver/pkg/endpoints/installer.go | 7 +++- .../pkg/registry/generic/registry/store.go | 15 +++++++ .../registry/generic/registry/store_test.go | 13 +++--- .../apiserver/pkg/registry/rest/rest.go | 2 +- .../pkg/server/genericapiserver_test.go | 8 ++++ .../pkg/registry/apiservice/etcd/etcd.go | 13 ++++-- .../pkg/registry/wardle/fischer/etcd.go | 9 +++-- .../pkg/registry/wardle/flunder/etcd.go | 9 +++-- 102 files changed, 608 insertions(+), 661 deletions(-) delete mode 100644 pkg/registry/registrytest/singularNameProvider.go 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, From 672e0b1e01fd23fa82ba164e27c87aee25d299b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Fri, 4 Nov 2022 16:05:45 +0300 Subject: [PATCH 05/10] Use correct singular name format for subresources --- .../apiserverinternal/storageversion/storage/storage.go | 2 +- pkg/registry/apps/daemonset/storage/storage.go | 2 +- pkg/registry/apps/deployment/storage/storage.go | 6 +++--- pkg/registry/apps/replicaset/storage/storage.go | 4 ++-- pkg/registry/apps/statefulset/storage/storage.go | 4 ++-- pkg/registry/authentication/selfsubjectreview/rest.go | 4 ++++ .../horizontalpodautoscaler/storage/storage.go | 2 +- pkg/registry/batch/cronjob/storage/storage.go | 2 +- pkg/registry/batch/job/storage/storage.go | 2 +- pkg/registry/certificates/certificates/storage/storage.go | 4 ++-- pkg/registry/core/namespace/storage/storage.go | 4 ++-- pkg/registry/core/node/rest/proxy.go | 2 +- pkg/registry/core/node/storage/storage.go | 2 +- pkg/registry/core/persistentvolume/storage/storage.go | 2 +- .../core/persistentvolumeclaim/storage/storage.go | 2 +- pkg/registry/core/pod/rest/log.go | 2 +- pkg/registry/core/pod/rest/subresources.go | 8 ++++---- pkg/registry/core/pod/storage/eviction.go | 2 +- pkg/registry/core/pod/storage/storage.go | 8 ++++---- .../core/replicationcontroller/storage/storage.go | 4 ++-- pkg/registry/core/resourcequota/storage/storage.go | 2 +- pkg/registry/core/service/proxy.go | 2 +- pkg/registry/core/service/storage/storage.go | 2 +- pkg/registry/core/serviceaccount/storage/token.go | 2 +- pkg/registry/flowcontrol/flowschema/storage/storage.go | 2 +- .../prioritylevelconfiguration/storage/storage.go | 2 +- pkg/registry/networking/ingress/storage/storage.go | 2 +- pkg/registry/networking/networkpolicy/storage/storage.go | 2 +- .../policy/poddisruptionbudget/storage/storage.go | 2 +- pkg/registry/storage/volumeattachment/storage/storage.go | 2 +- .../pkg/registry/customresourcedefinition/etcd.go | 2 +- .../kube-aggregator/pkg/registry/apiservice/etcd/etcd.go | 2 +- 32 files changed, 48 insertions(+), 44 deletions(-) diff --git a/pkg/registry/apiserverinternal/storageversion/storage/storage.go b/pkg/registry/apiserverinternal/storageversion/storage/storage.go index f4cf8bbec3d..92ede95afc7 100644 --- a/pkg/registry/apiserverinternal/storageversion/storage/storage.go +++ b/pkg/registry/apiserverinternal/storageversion/storage/storage.go @@ -104,5 +104,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/apps/daemonset/storage/storage.go b/pkg/registry/apps/daemonset/storage/storage.go index b2541039713..5f2246f0e95 100644 --- a/pkg/registry/apps/daemonset/storage/storage.go +++ b/pkg/registry/apps/daemonset/storage/storage.go @@ -119,5 +119,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/apps/deployment/storage/storage.go b/pkg/registry/apps/deployment/storage/storage.go index c94f5da9198..d5f2ce5297a 100644 --- a/pkg/registry/apps/deployment/storage/storage.go +++ b/pkg/registry/apps/deployment/storage/storage.go @@ -171,7 +171,7 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } // RollbackREST implements the REST endpoint for initiating the rollback of a deployment @@ -207,7 +207,7 @@ func (r *RollbackREST) Destroy() { var _ rest.SingularNameProvider = &RollbackREST{} func (r *RollbackREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/rollback" } var _ = rest.NamedCreater(&RollbackREST{}) @@ -357,7 +357,7 @@ func (r *ScaleREST) ConvertToTable(ctx context.Context, object runtime.Object, t var _ rest.SingularNameProvider = &ScaleREST{} func (r *ScaleREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/scale" } func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc { diff --git a/pkg/registry/apps/replicaset/storage/storage.go b/pkg/registry/apps/replicaset/storage/storage.go index b0d44428bb7..806c362676e 100644 --- a/pkg/registry/apps/replicaset/storage/storage.go +++ b/pkg/registry/apps/replicaset/storage/storage.go @@ -167,7 +167,7 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } // ScaleREST implements a Scale for ReplicaSet. @@ -247,7 +247,7 @@ func (r *ScaleREST) ConvertToTable(ctx context.Context, object runtime.Object, t var _ rest.SingularNameProvider = &ScaleREST{} func (r *ScaleREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/scale" } func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc { diff --git a/pkg/registry/apps/statefulset/storage/storage.go b/pkg/registry/apps/statefulset/storage/storage.go index b98ce47d7fa..ef9f8984e5d 100644 --- a/pkg/registry/apps/statefulset/storage/storage.go +++ b/pkg/registry/apps/statefulset/storage/storage.go @@ -155,7 +155,7 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } // Implement ShortNamesProvider @@ -241,7 +241,7 @@ func (r *ScaleREST) ConvertToTable(ctx context.Context, object runtime.Object, t var _ rest.SingularNameProvider = &ScaleREST{} func (r *ScaleREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/scale" } func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc { diff --git a/pkg/registry/authentication/selfsubjectreview/rest.go b/pkg/registry/authentication/selfsubjectreview/rest.go index 8d502315dfe..06af5b039e8 100644 --- a/pkg/registry/authentication/selfsubjectreview/rest.go +++ b/pkg/registry/authentication/selfsubjectreview/rest.go @@ -93,3 +93,7 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation return selfSAR, nil } + +func (r *REST) GetSingularName() string { + return "selfsubjectrulesreview" +} diff --git a/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go b/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go index 01677f5af12..4822f1bc540 100644 --- a/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go +++ b/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go @@ -119,5 +119,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/batch/cronjob/storage/storage.go b/pkg/registry/batch/cronjob/storage/storage.go index 52abf8d4a49..94b5b58f7db 100644 --- a/pkg/registry/batch/cronjob/storage/storage.go +++ b/pkg/registry/batch/cronjob/storage/storage.go @@ -117,5 +117,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/batch/job/storage/storage.go b/pkg/registry/batch/job/storage/storage.go index fbd509bf919..2959a1ca042 100644 --- a/pkg/registry/batch/job/storage/storage.go +++ b/pkg/registry/batch/job/storage/storage.go @@ -160,5 +160,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/certificates/certificates/storage/storage.go b/pkg/registry/certificates/certificates/storage/storage.go index 2a477369f12..045157653c0 100644 --- a/pkg/registry/certificates/certificates/storage/storage.go +++ b/pkg/registry/certificates/certificates/storage/storage.go @@ -120,7 +120,7 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } var _ = rest.Patcher(&StatusREST{}) @@ -161,7 +161,7 @@ func (r *ApprovalREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set var _ rest.SingularNameProvider = &ApprovalREST{} func (r *ApprovalREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/approval" } var _ = rest.Patcher(&ApprovalREST{}) diff --git a/pkg/registry/core/namespace/storage/storage.go b/pkg/registry/core/namespace/storage/storage.go index 18afd20e7f9..e9a37779f0d 100644 --- a/pkg/registry/core/namespace/storage/storage.go +++ b/pkg/registry/core/namespace/storage/storage.go @@ -342,7 +342,7 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } func (r *FinalizeREST) New() runtime.Object { @@ -370,5 +370,5 @@ func (r *FinalizeREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set var _ rest.SingularNameProvider = &FinalizeREST{} func (r *FinalizeREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/finalize" } diff --git a/pkg/registry/core/node/rest/proxy.go b/pkg/registry/core/node/rest/proxy.go index 4f4b855e284..d3c1c7122f2 100644 --- a/pkg/registry/core/node/rest/proxy.go +++ b/pkg/registry/core/node/rest/proxy.go @@ -69,7 +69,7 @@ func (r *ProxyREST) NewConnectOptions() (runtime.Object, bool, string) { var _ rest.SingularNameProvider = &ProxyREST{} func (r *ProxyREST) GetSingularName() string { - return r.Store.GetSingularName() + return r.Store.GetSingularName() + "/proxy" } // Connect returns a handler for the node proxy diff --git a/pkg/registry/core/node/storage/storage.go b/pkg/registry/core/node/storage/storage.go index faf741ebbc2..54c6b400dc0 100644 --- a/pkg/registry/core/node/storage/storage.go +++ b/pkg/registry/core/node/storage/storage.go @@ -96,7 +96,7 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } // NewStorage returns a NodeStorage object that will work against nodes. diff --git a/pkg/registry/core/persistentvolume/storage/storage.go b/pkg/registry/core/persistentvolume/storage/storage.go index 6809f1ee2ba..63014aa2667 100644 --- a/pkg/registry/core/persistentvolume/storage/storage.go +++ b/pkg/registry/core/persistentvolume/storage/storage.go @@ -114,5 +114,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/core/persistentvolumeclaim/storage/storage.go b/pkg/registry/core/persistentvolumeclaim/storage/storage.go index b580693fc17..611fbc013ee 100644 --- a/pkg/registry/core/persistentvolumeclaim/storage/storage.go +++ b/pkg/registry/core/persistentvolumeclaim/storage/storage.go @@ -158,5 +158,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/core/pod/rest/log.go b/pkg/registry/core/pod/rest/log.go index bd81f585727..b3180f334ee 100644 --- a/pkg/registry/core/pod/rest/log.go +++ b/pkg/registry/core/pod/rest/log.go @@ -137,5 +137,5 @@ func (r *LogREST) OverrideMetricsVerb(oldVerb string) (newVerb string) { var _ rest.SingularNameProvider = &LogREST{} func (r *LogREST) GetSingularName() string { - return r.Store.GetSingularName() + return r.Store.GetSingularName() + "/log" } diff --git a/pkg/registry/core/pod/rest/subresources.go b/pkg/registry/core/pod/rest/subresources.go index c2bdfa5b4ad..6972a8fb80e 100644 --- a/pkg/registry/core/pod/rest/subresources.go +++ b/pkg/registry/core/pod/rest/subresources.go @@ -83,7 +83,7 @@ func (r *ProxyREST) Connect(ctx context.Context, id string, opts runtime.Object, var _ rest.SingularNameProvider = &ProxyREST{} func (r *ProxyREST) GetSingularName() string { - return r.Store.GetSingularName() + return r.Store.GetSingularName() + "/proxy" } // Support both GET and POST methods. We must support GET for browsers that want to use WebSockets. @@ -135,7 +135,7 @@ func (r *AttachREST) ConnectMethods() []string { var _ rest.SingularNameProvider = &AttachREST{} func (r *AttachREST) GetSingularName() string { - return r.Store.GetSingularName() + return r.Store.GetSingularName() + "/attach" } // ExecREST implements the exec subresource for a Pod @@ -184,7 +184,7 @@ func (r *ExecREST) ConnectMethods() []string { var _ rest.SingularNameProvider = &ExecREST{} func (r *ExecREST) GetSingularName() string { - return r.Store.GetSingularName() + return r.Store.GetSingularName() + "/exec" } // PortForwardREST implements the portforward subresource for a Pod @@ -234,7 +234,7 @@ func (r *PortForwardREST) Connect(ctx context.Context, name string, opts runtime var _ rest.SingularNameProvider = &PortForwardREST{} func (r *PortForwardREST) GetSingularName() string { - return r.Store.GetSingularName() + return r.Store.GetSingularName() + "/portforward" } func newThrottledUpgradeAwareProxyHandler(location *url.URL, transport http.RoundTripper, wrapTransport, upgradeRequired bool, responder rest.Responder) *proxy.UpgradeAwareHandler { diff --git a/pkg/registry/core/pod/storage/eviction.go b/pkg/registry/core/pod/storage/eviction.go index 87d3991b44a..70876530297 100644 --- a/pkg/registry/core/pod/storage/eviction.go +++ b/pkg/registry/core/pod/storage/eviction.go @@ -106,7 +106,7 @@ func (r *EvictionREST) Destroy() { var _ rest.SingularNameProvider = &EvictionREST{} func (r *EvictionREST) GetSingularName() string { - return "pod" + return "pod/eviction" } // Propagate dry-run takes the dry-run option from the request and pushes it into the eviction object. diff --git a/pkg/registry/core/pod/storage/storage.go b/pkg/registry/core/pod/storage/storage.go index ddcbde69e3d..6add1f57471 100644 --- a/pkg/registry/core/pod/storage/storage.go +++ b/pkg/registry/core/pod/storage/storage.go @@ -167,7 +167,7 @@ func (r *BindingREST) Destroy() { var _ rest.SingularNameProvider = &BindingREST{} func (r *BindingREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/binding" } var _ = rest.NamedCreater(&BindingREST{}) @@ -289,7 +289,7 @@ func (r *LegacyBindingREST) Destroy() { var _ rest.SingularNameProvider = &LegacyBindingREST{} func (r *LegacyBindingREST) GetSingularName() string { - return r.bindingRest.GetSingularName() + return r.bindingRest.GetSingularName() + "/binding" } // Create ensures a pod is bound to a specific host. @@ -341,7 +341,7 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } // EphemeralContainersREST implements the REST endpoint for adding EphemeralContainers @@ -377,5 +377,5 @@ func (r *EphemeralContainersREST) Update(ctx context.Context, name string, objIn var _ rest.SingularNameProvider = &EphemeralContainersREST{} func (r *EphemeralContainersREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/ephemeralcontainers" } diff --git a/pkg/registry/core/replicationcontroller/storage/storage.go b/pkg/registry/core/replicationcontroller/storage/storage.go index e21d599379a..d8d6fcf124b 100644 --- a/pkg/registry/core/replicationcontroller/storage/storage.go +++ b/pkg/registry/core/replicationcontroller/storage/storage.go @@ -162,7 +162,7 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } type ScaleREST struct { @@ -226,7 +226,7 @@ func (r *ScaleREST) ConvertToTable(ctx context.Context, object runtime.Object, t var _ rest.SingularNameProvider = &ScaleREST{} func (r *ScaleREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/scale" } func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc { diff --git a/pkg/registry/core/resourcequota/storage/storage.go b/pkg/registry/core/resourcequota/storage/storage.go index 25f7e93c5e3..214ccdddecc 100644 --- a/pkg/registry/core/resourcequota/storage/storage.go +++ b/pkg/registry/core/resourcequota/storage/storage.go @@ -113,5 +113,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/core/service/proxy.go b/pkg/registry/core/service/proxy.go index c64caf5935a..92cf50ef199 100644 --- a/pkg/registry/core/service/proxy.go +++ b/pkg/registry/core/service/proxy.go @@ -80,7 +80,7 @@ func (r *ProxyREST) Connect(ctx context.Context, id string, opts runtime.Object, var _ rest.SingularNameProvider = &ProxyREST{} func (r *ProxyREST) GetSingularName() string { - return "service" + return "service/proxy" } func newThrottledUpgradeAwareProxyHandler(location *url.URL, transport http.RoundTripper, wrapTransport, upgradeRequired bool, responder rest.Responder) *proxy.UpgradeAwareHandler { diff --git a/pkg/registry/core/service/storage/storage.go b/pkg/registry/core/service/storage/storage.go index bcacad89044..179614ab062 100644 --- a/pkg/registry/core/service/storage/storage.go +++ b/pkg/registry/core/service/storage/storage.go @@ -199,7 +199,7 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } // We have a lot of functions that take a pair of "before" and "after" or diff --git a/pkg/registry/core/serviceaccount/storage/token.go b/pkg/registry/core/serviceaccount/storage/token.go index b59bb8d764c..1a78da264f2 100644 --- a/pkg/registry/core/serviceaccount/storage/token.go +++ b/pkg/registry/core/serviceaccount/storage/token.go @@ -52,7 +52,7 @@ func (r *TokenREST) Destroy() { var _ rest.SingularNameProvider = &TokenREST{} func (r *TokenREST) GetSingularName() string { - return "serviceaccount" + return "serviceaccount/token" } type TokenREST struct { diff --git a/pkg/registry/flowcontrol/flowschema/storage/storage.go b/pkg/registry/flowcontrol/flowschema/storage/storage.go index 380b309004f..73d662e9d33 100644 --- a/pkg/registry/flowcontrol/flowschema/storage/storage.go +++ b/pkg/registry/flowcontrol/flowschema/storage/storage.go @@ -112,5 +112,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/flowcontrol/prioritylevelconfiguration/storage/storage.go b/pkg/registry/flowcontrol/prioritylevelconfiguration/storage/storage.go index 0943814184f..e64e29ebcb8 100644 --- a/pkg/registry/flowcontrol/prioritylevelconfiguration/storage/storage.go +++ b/pkg/registry/flowcontrol/prioritylevelconfiguration/storage/storage.go @@ -112,5 +112,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/networking/ingress/storage/storage.go b/pkg/registry/networking/ingress/storage/storage.go index 8ca09f81014..28789e148bf 100644 --- a/pkg/registry/networking/ingress/storage/storage.go +++ b/pkg/registry/networking/ingress/storage/storage.go @@ -111,5 +111,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/networking/networkpolicy/storage/storage.go b/pkg/registry/networking/networkpolicy/storage/storage.go index cb453485f00..3cfbda1e905 100644 --- a/pkg/registry/networking/networkpolicy/storage/storage.go +++ b/pkg/registry/networking/networkpolicy/storage/storage.go @@ -109,5 +109,5 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/policy/poddisruptionbudget/storage/storage.go b/pkg/registry/policy/poddisruptionbudget/storage/storage.go index 260645c88be..bf1b93f5d20 100644 --- a/pkg/registry/policy/poddisruptionbudget/storage/storage.go +++ b/pkg/registry/policy/poddisruptionbudget/storage/storage.go @@ -108,5 +108,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } diff --git a/pkg/registry/storage/volumeattachment/storage/storage.go b/pkg/registry/storage/volumeattachment/storage/storage.go index 76fd823dab0..7265b8d9411 100644 --- a/pkg/registry/storage/volumeattachment/storage/storage.go +++ b/pkg/registry/storage/volumeattachment/storage/storage.go @@ -116,5 +116,5 @@ func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } 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 75b1323ca6e..f6be9d84c0e 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 @@ -222,5 +222,5 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { var _ rest.SingularNameProvider = &StatusREST{} func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } 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 624e47b82b2..2dfd18ccf07 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 @@ -172,5 +172,5 @@ func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { } func (r *StatusREST) GetSingularName() string { - return r.store.GetSingularName() + return r.store.GetSingularName() + "/status" } From 1abf94bec30706afbbeae7e4a1cbf4dbacbaa422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Fri, 18 Nov 2022 09:55:18 +0300 Subject: [PATCH 06/10] Remove GetSingularName for subresources --- .../storageversion/storage/storage.go | 6 ----- .../apps/daemonset/storage/storage.go | 6 ----- .../apps/deployment/storage/storage.go | 18 -------------- .../apps/replicaset/storage/storage.go | 12 ---------- .../apps/statefulset/storage/storage.go | 12 ---------- .../storage/storage.go | 6 ----- pkg/registry/batch/cronjob/storage/storage.go | 6 ----- pkg/registry/batch/job/storage/storage.go | 6 ----- .../certificates/storage/storage.go | 12 ---------- pkg/registry/core/endpoint/storage/storage.go | 2 +- .../core/namespace/storage/storage.go | 12 ---------- pkg/registry/core/node/rest/proxy.go | 6 ----- pkg/registry/core/node/storage/storage.go | 6 ----- .../core/persistentvolume/storage/storage.go | 6 ----- .../persistentvolumeclaim/storage/storage.go | 6 ----- pkg/registry/core/pod/rest/log.go | 6 ----- pkg/registry/core/pod/rest/subresources.go | 24 ------------------- pkg/registry/core/pod/storage/eviction.go | 6 ----- pkg/registry/core/pod/storage/storage.go | 18 -------------- .../replicationcontroller/storage/storage.go | 12 ---------- .../core/resourcequota/storage/storage.go | 6 ----- pkg/registry/core/service/proxy.go | 6 ----- pkg/registry/core/service/storage/storage.go | 6 ----- .../core/serviceaccount/storage/token.go | 6 ----- .../flowcontrol/flowschema/storage/storage.go | 6 ----- .../storage/storage.go | 6 ----- .../networking/ingress/storage/storage.go | 6 ----- .../networkpolicy/storage/storage.go | 6 ----- .../poddisruptionbudget/storage/storage.go | 6 ----- .../volumeattachment/storage/storage.go | 6 ----- .../registry/customresourcedefinition/etcd.go | 6 ----- .../apiserver/pkg/endpoints/installer.go | 10 ++++---- .../pkg/registry/apiservice/etcd/etcd.go | 4 ---- 33 files changed, 7 insertions(+), 261 deletions(-) diff --git a/pkg/registry/apiserverinternal/storageversion/storage/storage.go b/pkg/registry/apiserverinternal/storageversion/storage/storage.go index 92ede95afc7..86ee40d8c95 100644 --- a/pkg/registry/apiserverinternal/storageversion/storage/storage.go +++ b/pkg/registry/apiserverinternal/storageversion/storage/storage.go @@ -100,9 +100,3 @@ 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() + "/status" -} diff --git a/pkg/registry/apps/daemonset/storage/storage.go b/pkg/registry/apps/daemonset/storage/storage.go index 5f2246f0e95..16e91b3e873 100644 --- a/pkg/registry/apps/daemonset/storage/storage.go +++ b/pkg/registry/apps/daemonset/storage/storage.go @@ -115,9 +115,3 @@ 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() + "/status" -} diff --git a/pkg/registry/apps/deployment/storage/storage.go b/pkg/registry/apps/deployment/storage/storage.go index d5f2ce5297a..3d49c944e67 100644 --- a/pkg/registry/apps/deployment/storage/storage.go +++ b/pkg/registry/apps/deployment/storage/storage.go @@ -168,12 +168,6 @@ 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() + "/status" -} - // RollbackREST implements the REST endpoint for initiating the rollback of a deployment type RollbackREST struct { store *genericregistry.Store @@ -204,12 +198,6 @@ func (r *RollbackREST) Destroy() { // we don't destroy it here explicitly. } -var _ rest.SingularNameProvider = &RollbackREST{} - -func (r *RollbackREST) GetSingularName() string { - return r.store.GetSingularName() + "/rollback" -} - var _ = rest.NamedCreater(&RollbackREST{}) // Create runs rollback for deployment @@ -354,12 +342,6 @@ 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() + "/scale" -} - 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/replicaset/storage/storage.go b/pkg/registry/apps/replicaset/storage/storage.go index 806c362676e..28131b416e8 100644 --- a/pkg/registry/apps/replicaset/storage/storage.go +++ b/pkg/registry/apps/replicaset/storage/storage.go @@ -164,12 +164,6 @@ 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() + "/status" -} - // ScaleREST implements a Scale for ReplicaSet. type ScaleREST struct { store *genericregistry.Store @@ -244,12 +238,6 @@ 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() + "/scale" -} - 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/statefulset/storage/storage.go b/pkg/registry/apps/statefulset/storage/storage.go index ef9f8984e5d..73bd391b259 100644 --- a/pkg/registry/apps/statefulset/storage/storage.go +++ b/pkg/registry/apps/statefulset/storage/storage.go @@ -152,12 +152,6 @@ 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() + "/status" -} - // Implement ShortNamesProvider var _ rest.ShortNamesProvider = &REST{} @@ -238,12 +232,6 @@ 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() + "/scale" -} - 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/autoscaling/horizontalpodautoscaler/storage/storage.go b/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go index 4822f1bc540..bedd6814756 100644 --- a/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go +++ b/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go @@ -115,9 +115,3 @@ 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() + "/status" -} diff --git a/pkg/registry/batch/cronjob/storage/storage.go b/pkg/registry/batch/cronjob/storage/storage.go index 94b5b58f7db..a963d140517 100644 --- a/pkg/registry/batch/cronjob/storage/storage.go +++ b/pkg/registry/batch/cronjob/storage/storage.go @@ -113,9 +113,3 @@ 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() + "/status" -} diff --git a/pkg/registry/batch/job/storage/storage.go b/pkg/registry/batch/job/storage/storage.go index 2959a1ca042..9ca9d5f974a 100644 --- a/pkg/registry/batch/job/storage/storage.go +++ b/pkg/registry/batch/job/storage/storage.go @@ -156,9 +156,3 @@ 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() + "/status" -} diff --git a/pkg/registry/certificates/certificates/storage/storage.go b/pkg/registry/certificates/certificates/storage/storage.go index 045157653c0..d45391924f2 100644 --- a/pkg/registry/certificates/certificates/storage/storage.go +++ b/pkg/registry/certificates/certificates/storage/storage.go @@ -117,12 +117,6 @@ 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() + "/status" -} - var _ = rest.Patcher(&StatusREST{}) // ApprovalREST implements the REST endpoint for changing the approval state of a CSR. @@ -158,10 +152,4 @@ 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() + "/approval" -} - var _ = rest.Patcher(&ApprovalREST{}) diff --git a/pkg/registry/core/endpoint/storage/storage.go b/pkg/registry/core/endpoint/storage/storage.go index c82deb687d1..a3c31d3eb36 100644 --- a/pkg/registry/core/endpoint/storage/storage.go +++ b/pkg/registry/core/endpoint/storage/storage.go @@ -39,7 +39,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { NewFunc: func() runtime.Object { return &api.Endpoints{} }, NewListFunc: func() runtime.Object { return &api.EndpointsList{} }, DefaultQualifiedResource: api.Resource("endpoints"), - SingularQualifiedResource: api.Resource("endpoint"), + SingularQualifiedResource: api.Resource("endpoints"), CreateStrategy: endpoint.Strategy, UpdateStrategy: endpoint.Strategy, diff --git a/pkg/registry/core/namespace/storage/storage.go b/pkg/registry/core/namespace/storage/storage.go index e9a37779f0d..e88fad7fa8a 100644 --- a/pkg/registry/core/namespace/storage/storage.go +++ b/pkg/registry/core/namespace/storage/storage.go @@ -339,12 +339,6 @@ 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() + "/status" -} - func (r *FinalizeREST) New() runtime.Object { return r.store.New() } @@ -366,9 +360,3 @@ 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() + "/finalize" -} diff --git a/pkg/registry/core/node/rest/proxy.go b/pkg/registry/core/node/rest/proxy.go index d3c1c7122f2..40e6431b40b 100644 --- a/pkg/registry/core/node/rest/proxy.go +++ b/pkg/registry/core/node/rest/proxy.go @@ -66,12 +66,6 @@ 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() + "/proxy" -} - // 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 54c6b400dc0..5b6ce5eb0af 100644 --- a/pkg/registry/core/node/storage/storage.go +++ b/pkg/registry/core/node/storage/storage.go @@ -93,12 +93,6 @@ 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() + "/status" -} - // 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{ diff --git a/pkg/registry/core/persistentvolume/storage/storage.go b/pkg/registry/core/persistentvolume/storage/storage.go index 63014aa2667..41422229bcf 100644 --- a/pkg/registry/core/persistentvolume/storage/storage.go +++ b/pkg/registry/core/persistentvolume/storage/storage.go @@ -110,9 +110,3 @@ 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() + "/status" -} diff --git a/pkg/registry/core/persistentvolumeclaim/storage/storage.go b/pkg/registry/core/persistentvolumeclaim/storage/storage.go index 611fbc013ee..4ba7b954242 100644 --- a/pkg/registry/core/persistentvolumeclaim/storage/storage.go +++ b/pkg/registry/core/persistentvolumeclaim/storage/storage.go @@ -154,9 +154,3 @@ 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() + "/status" -} diff --git a/pkg/registry/core/pod/rest/log.go b/pkg/registry/core/pod/rest/log.go index b3180f334ee..e6b02069b28 100644 --- a/pkg/registry/core/pod/rest/log.go +++ b/pkg/registry/core/pod/rest/log.go @@ -133,9 +133,3 @@ func (r *LogREST) OverrideMetricsVerb(oldVerb string) (newVerb string) { return } - -var _ rest.SingularNameProvider = &LogREST{} - -func (r *LogREST) GetSingularName() string { - return r.Store.GetSingularName() + "/log" -} diff --git a/pkg/registry/core/pod/rest/subresources.go b/pkg/registry/core/pod/rest/subresources.go index 6972a8fb80e..76e0cdd4ffb 100644 --- a/pkg/registry/core/pod/rest/subresources.go +++ b/pkg/registry/core/pod/rest/subresources.go @@ -80,12 +80,6 @@ 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() + "/proxy" -} - // Support both GET and POST methods. We must support GET for browsers that want to use WebSockets. var upgradeableMethods = []string{"GET", "POST"} @@ -132,12 +126,6 @@ func (r *AttachREST) ConnectMethods() []string { return upgradeableMethods } -var _ rest.SingularNameProvider = &AttachREST{} - -func (r *AttachREST) GetSingularName() string { - return r.Store.GetSingularName() + "/attach" -} - // ExecREST implements the exec subresource for a Pod type ExecREST struct { Store *genericregistry.Store @@ -181,12 +169,6 @@ func (r *ExecREST) ConnectMethods() []string { return upgradeableMethods } -var _ rest.SingularNameProvider = &ExecREST{} - -func (r *ExecREST) GetSingularName() string { - return r.Store.GetSingularName() + "/exec" -} - // PortForwardREST implements the portforward subresource for a Pod type PortForwardREST struct { Store *genericregistry.Store @@ -231,12 +213,6 @@ 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() + "/portforward" -} - 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 70876530297..ee8182c4135 100644 --- a/pkg/registry/core/pod/storage/eviction.go +++ b/pkg/registry/core/pod/storage/eviction.go @@ -103,12 +103,6 @@ func (r *EvictionREST) Destroy() { // we don't destroy it here explicitly. } -var _ rest.SingularNameProvider = &EvictionREST{} - -func (r *EvictionREST) GetSingularName() string { - return "pod/eviction" -} - // 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 6add1f57471..4a10f4fd35e 100644 --- a/pkg/registry/core/pod/storage/storage.go +++ b/pkg/registry/core/pod/storage/storage.go @@ -164,12 +164,6 @@ func (r *BindingREST) Destroy() { // we don't destroy it here explicitly. } -var _ rest.SingularNameProvider = &BindingREST{} - -func (r *BindingREST) GetSingularName() string { - return r.store.GetSingularName() + "/binding" -} - var _ = rest.NamedCreater(&BindingREST{}) // Create ensures a pod is bound to a specific host. @@ -338,12 +332,6 @@ 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() + "/status" -} - // EphemeralContainersREST implements the REST endpoint for adding EphemeralContainers type EphemeralContainersREST struct { store *genericregistry.Store @@ -373,9 +361,3 @@ 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() + "/ephemeralcontainers" -} diff --git a/pkg/registry/core/replicationcontroller/storage/storage.go b/pkg/registry/core/replicationcontroller/storage/storage.go index d8d6fcf124b..edc5c7c8dd0 100644 --- a/pkg/registry/core/replicationcontroller/storage/storage.go +++ b/pkg/registry/core/replicationcontroller/storage/storage.go @@ -159,12 +159,6 @@ 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() + "/status" -} - type ScaleREST struct { store *genericregistry.Store } @@ -223,12 +217,6 @@ 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() + "/scale" -} - 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/resourcequota/storage/storage.go b/pkg/registry/core/resourcequota/storage/storage.go index 214ccdddecc..c67038f1df4 100644 --- a/pkg/registry/core/resourcequota/storage/storage.go +++ b/pkg/registry/core/resourcequota/storage/storage.go @@ -109,9 +109,3 @@ 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() + "/status" -} diff --git a/pkg/registry/core/service/proxy.go b/pkg/registry/core/service/proxy.go index 92cf50ef199..f0eb9d0788a 100644 --- a/pkg/registry/core/service/proxy.go +++ b/pkg/registry/core/service/proxy.go @@ -77,12 +77,6 @@ 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/proxy" -} - 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 179614ab062..4ff923f5e4f 100644 --- a/pkg/registry/core/service/storage/storage.go +++ b/pkg/registry/core/service/storage/storage.go @@ -196,12 +196,6 @@ 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() + "/status" -} - // 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/serviceaccount/storage/token.go b/pkg/registry/core/serviceaccount/storage/token.go index 1a78da264f2..6f840e53154 100644 --- a/pkg/registry/core/serviceaccount/storage/token.go +++ b/pkg/registry/core/serviceaccount/storage/token.go @@ -49,12 +49,6 @@ func (r *TokenREST) Destroy() { // here explicitly. } -var _ rest.SingularNameProvider = &TokenREST{} - -func (r *TokenREST) GetSingularName() string { - return "serviceaccount/token" -} - type TokenREST struct { svcaccts getter pods getter diff --git a/pkg/registry/flowcontrol/flowschema/storage/storage.go b/pkg/registry/flowcontrol/flowschema/storage/storage.go index 73d662e9d33..5a1146201a6 100644 --- a/pkg/registry/flowcontrol/flowschema/storage/storage.go +++ b/pkg/registry/flowcontrol/flowschema/storage/storage.go @@ -108,9 +108,3 @@ 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() + "/status" -} diff --git a/pkg/registry/flowcontrol/prioritylevelconfiguration/storage/storage.go b/pkg/registry/flowcontrol/prioritylevelconfiguration/storage/storage.go index e64e29ebcb8..2149b5906f4 100644 --- a/pkg/registry/flowcontrol/prioritylevelconfiguration/storage/storage.go +++ b/pkg/registry/flowcontrol/prioritylevelconfiguration/storage/storage.go @@ -108,9 +108,3 @@ 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() + "/status" -} diff --git a/pkg/registry/networking/ingress/storage/storage.go b/pkg/registry/networking/ingress/storage/storage.go index 28789e148bf..9018055af76 100644 --- a/pkg/registry/networking/ingress/storage/storage.go +++ b/pkg/registry/networking/ingress/storage/storage.go @@ -107,9 +107,3 @@ 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() + "/status" -} diff --git a/pkg/registry/networking/networkpolicy/storage/storage.go b/pkg/registry/networking/networkpolicy/storage/storage.go index 3cfbda1e905..0445c98a4c2 100644 --- a/pkg/registry/networking/networkpolicy/storage/storage.go +++ b/pkg/registry/networking/networkpolicy/storage/storage.go @@ -105,9 +105,3 @@ 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() + "/status" -} diff --git a/pkg/registry/policy/poddisruptionbudget/storage/storage.go b/pkg/registry/policy/poddisruptionbudget/storage/storage.go index bf1b93f5d20..0c7b1ba1f7b 100644 --- a/pkg/registry/policy/poddisruptionbudget/storage/storage.go +++ b/pkg/registry/policy/poddisruptionbudget/storage/storage.go @@ -104,9 +104,3 @@ 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() + "/status" -} diff --git a/pkg/registry/storage/volumeattachment/storage/storage.go b/pkg/registry/storage/volumeattachment/storage/storage.go index 7265b8d9411..1d213730a74 100644 --- a/pkg/registry/storage/volumeattachment/storage/storage.go +++ b/pkg/registry/storage/volumeattachment/storage/storage.go @@ -112,9 +112,3 @@ 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() + "/status" -} 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 f6be9d84c0e..6300a08ce43 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 @@ -218,9 +218,3 @@ 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() + "/status" -} diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go b/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go index 63d21706209..2c4d7b95793 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go @@ -1080,11 +1080,13 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag if categoriesProvider, ok := storage.(rest.CategoriesProvider); ok { apiResource.Categories = categoriesProvider.Categories() } - singularNameProvider, ok := storage.(rest.SingularNameProvider) - if !ok { - return nil, nil, fmt.Errorf("resource %s must implement SingularNameProvider", resource) + if !isSubresource { + singularNameProvider, ok := storage.(rest.SingularNameProvider) + if !ok { + return nil, nil, fmt.Errorf("resource %s must implement SingularNameProvider", resource) + } + apiResource.SingularName = singularNameProvider.GetSingularName() } - apiResource.SingularName = singularNameProvider.GetSingularName() if gvkProvider, ok := storage.(rest.GroupVersionKindProvider); ok { gvk := gvkProvider.GroupVersionKind(a.group.GroupVersion) 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 2dfd18ccf07..42dddcd8315 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 @@ -170,7 +170,3 @@ 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() + "/status" -} From d14b7781e2161d8239d8f6e3480f064ebf30139b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Fri, 18 Nov 2022 10:12:49 +0300 Subject: [PATCH 07/10] Use casted SingularName for rbac types --- pkg/registry/core/pod/storage/storage.go | 6 ------ pkg/registry/rbac/clusterrole/policybased/storage.go | 6 +++++- pkg/registry/rbac/clusterrolebinding/policybased/storage.go | 6 +++++- pkg/registry/rbac/role/policybased/storage.go | 6 +++++- pkg/registry/rbac/rolebinding/policybased/storage.go | 6 +++++- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/pkg/registry/core/pod/storage/storage.go b/pkg/registry/core/pod/storage/storage.go index 4a10f4fd35e..2ec0f3c5615 100644 --- a/pkg/registry/core/pod/storage/storage.go +++ b/pkg/registry/core/pod/storage/storage.go @@ -280,12 +280,6 @@ func (r *LegacyBindingREST) Destroy() { // we don't destroy it here explicitly. } -var _ rest.SingularNameProvider = &LegacyBindingREST{} - -func (r *LegacyBindingREST) GetSingularName() string { - return r.bindingRest.GetSingularName() + "/binding" -} - // 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) diff --git a/pkg/registry/rbac/clusterrole/policybased/storage.go b/pkg/registry/rbac/clusterrole/policybased/storage.go index 02ba90a9597..1e113cd9e07 100644 --- a/pkg/registry/rbac/clusterrole/policybased/storage.go +++ b/pkg/registry/rbac/clusterrole/policybased/storage.go @@ -128,5 +128,9 @@ func hasAggregationRule(clusterRole *rbac.ClusterRole) bool { var _ rest.SingularNameProvider = &Storage{} func (s *Storage) GetSingularName() string { - return "clusterrole" + svp, ok := s.StandardStorage.(rest.SingularNameProvider) + if !ok { + return "" + } + return svp.GetSingularName() } diff --git a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go index 3ddf0c597c4..1c3cd3431f3 100644 --- a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go +++ b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go @@ -131,5 +131,9 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec var _ rest.SingularNameProvider = &Storage{} func (s *Storage) GetSingularName() string { - return "clusterrolebinding" + svp, ok := s.StandardStorage.(rest.SingularNameProvider) + if !ok { + return "" + } + return svp.GetSingularName() } diff --git a/pkg/registry/rbac/role/policybased/storage.go b/pkg/registry/rbac/role/policybased/storage.go index 97743dabde4..36ac26dd3e9 100644 --- a/pkg/registry/rbac/role/policybased/storage.go +++ b/pkg/registry/rbac/role/policybased/storage.go @@ -103,5 +103,9 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec var _ rest.SingularNameProvider = &Storage{} func (s *Storage) GetSingularName() string { - return "role" + svp, ok := s.StandardStorage.(rest.SingularNameProvider) + if !ok { + return "" + } + return svp.GetSingularName() } diff --git a/pkg/registry/rbac/rolebinding/policybased/storage.go b/pkg/registry/rbac/rolebinding/policybased/storage.go index 48177edf81d..10e1a656201 100644 --- a/pkg/registry/rbac/rolebinding/policybased/storage.go +++ b/pkg/registry/rbac/rolebinding/policybased/storage.go @@ -146,5 +146,9 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec var _ rest.SingularNameProvider = &Storage{} func (s *Storage) GetSingularName() string { - return "rolebinding" + svp, ok := s.StandardStorage.(rest.SingularNameProvider) + if !ok { + return "" + } + return svp.GetSingularName() } From 23e28995569b1b88d82f53385e4276baae445cd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Fri, 18 Nov 2022 11:27:54 +0300 Subject: [PATCH 08/10] Implement GetSingularName for LegacyBindingREST LegacyBindingREST is only used for `bindings` resource. It is not a subresource and that's why it is required to implement `GetSingularName` function. However, there is no need to implement this function for BindingREST because it is only used for binding subresource. That's why, this function statically adds GetSingularName for LegacyBindingREST. --- pkg/registry/core/pod/storage/storage.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/registry/core/pod/storage/storage.go b/pkg/registry/core/pod/storage/storage.go index 2ec0f3c5615..0109c643bdf 100644 --- a/pkg/registry/core/pod/storage/storage.go +++ b/pkg/registry/core/pod/storage/storage.go @@ -289,6 +289,10 @@ func (r *LegacyBindingREST) Create(ctx context.Context, obj runtime.Object, crea return r.bindingRest.Create(ctx, metadata.GetName(), obj, createValidation, options) } +func (r *LegacyBindingREST) GetSingularName() string { + return "bindings" +} + // StatusREST implements the REST endpoint for changing the status of a pod. type StatusREST struct { store *genericregistry.Store From 1f54f610e46b1db390fc7d2a76d1716c842fd51d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Fri, 18 Nov 2022 13:11:16 +0300 Subject: [PATCH 09/10] minor integration test fixes and more singular resource --- .../validatingadmissionpolicy/storage/storage.go | 3 ++- .../validatingadmissionpolicybinding/storage/storage.go | 3 ++- pkg/registry/authentication/selfsubjectreview/rest.go | 2 ++ pkg/registry/rbac/clusterrole/policybased/storage.go | 4 ++-- .../rbac/clusterrolebinding/policybased/storage.go | 4 ++-- pkg/registry/rbac/role/policybased/storage.go | 4 ++-- pkg/registry/rbac/rolebinding/policybased/storage.go | 4 ++-- pkg/registry/resource/podscheduling/storage/storage.go | 9 +++++---- pkg/registry/resource/resourceclaim/storage/storage.go | 9 +++++---- .../resource/resourceclaimtemplate/storage/storage.go | 7 ++++--- pkg/registry/resource/resourceclass/storage/storage.go | 7 ++++--- test/cmd/discovery.sh | 4 ++-- 12 files changed, 34 insertions(+), 26 deletions(-) diff --git a/pkg/registry/admissionregistration/validatingadmissionpolicy/storage/storage.go b/pkg/registry/admissionregistration/validatingadmissionpolicy/storage/storage.go index 2c2f765e740..dfdf9339a17 100644 --- a/pkg/registry/admissionregistration/validatingadmissionpolicy/storage/storage.go +++ b/pkg/registry/admissionregistration/validatingadmissionpolicy/storage/storage.go @@ -47,7 +47,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter, authorizer authorizer.Authori ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*admissionregistration.ValidatingAdmissionPolicy).Name, nil }, - DefaultQualifiedResource: groupResource, + DefaultQualifiedResource: groupResource, + SingularQualifiedResource: admissionregistration.Resource("validatingadmissionpolicy"), CreateStrategy: strategy, UpdateStrategy: strategy, diff --git a/pkg/registry/admissionregistration/validatingadmissionpolicybinding/storage/storage.go b/pkg/registry/admissionregistration/validatingadmissionpolicybinding/storage/storage.go index 0f0afa4b39b..8d8b9ee9ffb 100644 --- a/pkg/registry/admissionregistration/validatingadmissionpolicybinding/storage/storage.go +++ b/pkg/registry/admissionregistration/validatingadmissionpolicybinding/storage/storage.go @@ -50,7 +50,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter, authorizer authorizer.Authori ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*admissionregistration.ValidatingAdmissionPolicyBinding).Name, nil }, - DefaultQualifiedResource: groupResource, + DefaultQualifiedResource: groupResource, + SingularQualifiedResource: admissionregistration.Resource("validatingadmissionpolicybinding"), CreateStrategy: strategy, UpdateStrategy: strategy, diff --git a/pkg/registry/authentication/selfsubjectreview/rest.go b/pkg/registry/authentication/selfsubjectreview/rest.go index 06af5b039e8..9c1978104c0 100644 --- a/pkg/registry/authentication/selfsubjectreview/rest.go +++ b/pkg/registry/authentication/selfsubjectreview/rest.go @@ -94,6 +94,8 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation return selfSAR, nil } +var _ rest.SingularNameProvider = &REST{} + func (r *REST) GetSingularName() string { return "selfsubjectrulesreview" } diff --git a/pkg/registry/rbac/clusterrole/policybased/storage.go b/pkg/registry/rbac/clusterrole/policybased/storage.go index 1e113cd9e07..260f75eb02f 100644 --- a/pkg/registry/rbac/clusterrole/policybased/storage.go +++ b/pkg/registry/rbac/clusterrole/policybased/storage.go @@ -128,9 +128,9 @@ func hasAggregationRule(clusterRole *rbac.ClusterRole) bool { var _ rest.SingularNameProvider = &Storage{} func (s *Storage) GetSingularName() string { - svp, ok := s.StandardStorage.(rest.SingularNameProvider) + snp, ok := s.StandardStorage.(rest.SingularNameProvider) if !ok { return "" } - return svp.GetSingularName() + return snp.GetSingularName() } diff --git a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go index 1c3cd3431f3..3e4b9d725f5 100644 --- a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go +++ b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go @@ -131,9 +131,9 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec var _ rest.SingularNameProvider = &Storage{} func (s *Storage) GetSingularName() string { - svp, ok := s.StandardStorage.(rest.SingularNameProvider) + snp, ok := s.StandardStorage.(rest.SingularNameProvider) if !ok { return "" } - return svp.GetSingularName() + return snp.GetSingularName() } diff --git a/pkg/registry/rbac/role/policybased/storage.go b/pkg/registry/rbac/role/policybased/storage.go index 36ac26dd3e9..83f49e02dec 100644 --- a/pkg/registry/rbac/role/policybased/storage.go +++ b/pkg/registry/rbac/role/policybased/storage.go @@ -103,9 +103,9 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec var _ rest.SingularNameProvider = &Storage{} func (s *Storage) GetSingularName() string { - svp, ok := s.StandardStorage.(rest.SingularNameProvider) + snp, ok := s.StandardStorage.(rest.SingularNameProvider) if !ok { return "" } - return svp.GetSingularName() + return snp.GetSingularName() } diff --git a/pkg/registry/rbac/rolebinding/policybased/storage.go b/pkg/registry/rbac/rolebinding/policybased/storage.go index 10e1a656201..21171ec4022 100644 --- a/pkg/registry/rbac/rolebinding/policybased/storage.go +++ b/pkg/registry/rbac/rolebinding/policybased/storage.go @@ -146,9 +146,9 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec var _ rest.SingularNameProvider = &Storage{} func (s *Storage) GetSingularName() string { - svp, ok := s.StandardStorage.(rest.SingularNameProvider) + snp, ok := s.StandardStorage.(rest.SingularNameProvider) if !ok { return "" } - return svp.GetSingularName() + return snp.GetSingularName() } diff --git a/pkg/registry/resource/podscheduling/storage/storage.go b/pkg/registry/resource/podscheduling/storage/storage.go index b977f283b85..5c066d2860e 100644 --- a/pkg/registry/resource/podscheduling/storage/storage.go +++ b/pkg/registry/resource/podscheduling/storage/storage.go @@ -40,10 +40,11 @@ type REST struct { // NewREST returns a RESTStorage object that will work against PodSchedulings. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &resource.PodScheduling{} }, - NewListFunc: func() runtime.Object { return &resource.PodSchedulingList{} }, - PredicateFunc: podscheduling.Match, - DefaultQualifiedResource: resource.Resource("podschedulings"), + NewFunc: func() runtime.Object { return &resource.PodScheduling{} }, + NewListFunc: func() runtime.Object { return &resource.PodSchedulingList{} }, + PredicateFunc: podscheduling.Match, + DefaultQualifiedResource: resource.Resource("podschedulings"), + SingularQualifiedResource: resource.Resource("podscheduling"), CreateStrategy: podscheduling.Strategy, UpdateStrategy: podscheduling.Strategy, diff --git a/pkg/registry/resource/resourceclaim/storage/storage.go b/pkg/registry/resource/resourceclaim/storage/storage.go index 959cb680bfe..5784c6e309c 100644 --- a/pkg/registry/resource/resourceclaim/storage/storage.go +++ b/pkg/registry/resource/resourceclaim/storage/storage.go @@ -40,10 +40,11 @@ type REST struct { // NewREST returns a RESTStorage object that will work against ResourceClaims. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &resource.ResourceClaim{} }, - NewListFunc: func() runtime.Object { return &resource.ResourceClaimList{} }, - PredicateFunc: resourceclaim.Match, - DefaultQualifiedResource: resource.Resource("resourceclaims"), + NewFunc: func() runtime.Object { return &resource.ResourceClaim{} }, + NewListFunc: func() runtime.Object { return &resource.ResourceClaimList{} }, + PredicateFunc: resourceclaim.Match, + DefaultQualifiedResource: resource.Resource("resourceclaims"), + SingularQualifiedResource: resource.Resource("resourceclaim"), CreateStrategy: resourceclaim.Strategy, UpdateStrategy: resourceclaim.Strategy, diff --git a/pkg/registry/resource/resourceclaimtemplate/storage/storage.go b/pkg/registry/resource/resourceclaimtemplate/storage/storage.go index 282db91006d..f32851f9550 100644 --- a/pkg/registry/resource/resourceclaimtemplate/storage/storage.go +++ b/pkg/registry/resource/resourceclaimtemplate/storage/storage.go @@ -35,9 +35,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against ResourceClass. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &resource.ResourceClaimTemplate{} }, - NewListFunc: func() runtime.Object { return &resource.ResourceClaimTemplateList{} }, - DefaultQualifiedResource: resource.Resource("resourceclaimtemplates"), + NewFunc: func() runtime.Object { return &resource.ResourceClaimTemplate{} }, + NewListFunc: func() runtime.Object { return &resource.ResourceClaimTemplateList{} }, + DefaultQualifiedResource: resource.Resource("resourceclaimtemplates"), + SingularQualifiedResource: resource.Resource("resourceclaimtemplate"), CreateStrategy: resourceclaimtemplate.Strategy, UpdateStrategy: resourceclaimtemplate.Strategy, diff --git a/pkg/registry/resource/resourceclass/storage/storage.go b/pkg/registry/resource/resourceclass/storage/storage.go index 310488ab04e..ad7d283b954 100644 --- a/pkg/registry/resource/resourceclass/storage/storage.go +++ b/pkg/registry/resource/resourceclass/storage/storage.go @@ -35,9 +35,10 @@ type REST struct { // NewREST returns a RESTStorage object that will work against ResourceClass. func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &resource.ResourceClass{} }, - NewListFunc: func() runtime.Object { return &resource.ResourceClassList{} }, - DefaultQualifiedResource: resource.Resource("resourceclasses"), + NewFunc: func() runtime.Object { return &resource.ResourceClass{} }, + NewListFunc: func() runtime.Object { return &resource.ResourceClassList{} }, + DefaultQualifiedResource: resource.Resource("resourceclasses"), + SingularQualifiedResource: resource.Resource("resourceclass"), CreateStrategy: resourceclass.Strategy, UpdateStrategy: resourceclass.Strategy, diff --git a/test/cmd/discovery.sh b/test/cmd/discovery.sh index daec7052202..4979f4356d1 100755 --- a/test/cmd/discovery.sh +++ b/test/cmd/discovery.sh @@ -91,7 +91,7 @@ spec: __EOF__ # Test that we can list this new custom resource - kube::test::wait_object_assert customresourcedefinitions "{{range.items}}{{if eq ${id_field:?} \\\"examples.test.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'examples.test.com:' + kube::test::wait_object_assert customresourcedefinitions "{{range.items}}{{if eq ${id_field:?} \"examples.test.com\"}}{{$id_field}}:{{end}}{{end}}" 'examples.test.com:' kubectl create -f - << __EOF__ apiVersion: test.com/v1 @@ -169,7 +169,7 @@ spec: __EOF__ # Test that we can list this new custom resource - kube::test::wait_object_assert customresourcedefinitions "{{range.items}}{{if eq ${id_field:?} \\\"examples.test.com\\\"}}{{$id_field}}:{{end}}{{end}}" 'examples.test.com:' + kube::test::wait_object_assert customresourcedefinitions "{{range.items}}{{if eq ${id_field:?} \"examples.test.com\"}}{{$id_field}}:{{end}}{{end}}" 'examples.test.com:' kubectl create -f - << __EOF__ apiVersion: test.com/v1 From 43a889fc65bc4919794ce9d43282fd2166856ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Mon, 21 Nov 2022 09:59:37 +0300 Subject: [PATCH 10/10] Add integration test to test singularnames for all resources --- pkg/registry/core/node/storage/storage.go | 3 --- pkg/registry/core/pod/storage/storage.go | 2 +- .../apiserver/discovery/discovery_test.go | 27 +++++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/pkg/registry/core/node/storage/storage.go b/pkg/registry/core/node/storage/storage.go index 5b6ce5eb0af..912dcb84171 100644 --- a/pkg/registry/core/node/storage/storage.go +++ b/pkg/registry/core/node/storage/storage.go @@ -168,9 +168,6 @@ func (r *REST) ResourceLocation(ctx context.Context, id string) (*url.URL, http. return node.ResourceLocation(r, r.connection, r.proxyTransport, ctx, id) } -// Implement ShortNamesProvider -var _ rest.ShortNamesProvider = &REST{} - // ShortNames implements the ShortNamesProvider interface. Returns a list of short names for a resource. func (r *REST) ShortNames() []string { return []string{"no"} diff --git a/pkg/registry/core/pod/storage/storage.go b/pkg/registry/core/pod/storage/storage.go index 0109c643bdf..723ef4778e9 100644 --- a/pkg/registry/core/pod/storage/storage.go +++ b/pkg/registry/core/pod/storage/storage.go @@ -290,7 +290,7 @@ func (r *LegacyBindingREST) Create(ctx context.Context, obj runtime.Object, crea } func (r *LegacyBindingREST) GetSingularName() string { - return "bindings" + return "binding" } // StatusREST implements the REST endpoint for changing the status of a pod. diff --git a/test/integration/apiserver/discovery/discovery_test.go b/test/integration/apiserver/discovery/discovery_test.go index c6b7caaa477..b27dbecb2b4 100644 --- a/test/integration/apiserver/discovery/discovery_test.go +++ b/test/integration/apiserver/discovery/discovery_test.go @@ -690,6 +690,33 @@ func TestGroupPriorty(t *testing.T) { }) } +func TestSingularNames(t *testing.T) { + server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--runtime-config=api/all=true"}, framework.SharedEtcd()) + t.Cleanup(server.TearDownFn) + + kubeClientSet, err := kubernetes.NewForConfig(server.ClientConfig) + require.NoError(t, err) + + _, resources, err := kubeClientSet.Discovery().ServerGroupsAndResources() + require.NoError(t, err) + + for _, rr := range resources { + for _, r := range rr.APIResources { + if strings.Contains(r.Name, "/") { + continue + } + if r.SingularName == "" { + t.Errorf("missing singularName for resource %q in %q", r.Name, rr.GroupVersion) + continue + } + if r.SingularName != strings.ToLower(r.Kind) { + t.Errorf("expected singularName for resource %q in %q to be %q, got %q", r.Name, rr.GroupVersion, strings.ToLower(r.Kind), r.SingularName) + continue + } + } + } +} + func makeCRDSpec(group string, kind string, namespaced bool, versions []string, categories ...string) apiextensionsv1.CustomResourceDefinitionSpec { scope := apiextensionsv1.NamespaceScoped if !namespaced {