Skip to content

Commit 5914dee

Browse files
author
k8s-merge-robot
committed
Merge pull request kubernetes#19380 from brendandburns/apiresource
Auto commit by PR queue bot
2 parents d7dd663 + 7953338 commit 5914dee

File tree

6 files changed

+39
-8
lines changed

6 files changed

+39
-8
lines changed

pkg/api/rest/rest.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ type Storage interface {
5555
New() runtime.Object
5656
}
5757

58+
// KindProvider specifies a different kind for its API than for its internal storage. This is necessary for external
59+
// objects that are not compiled into the api server. For such objects, there is no in-memory representation for
60+
// the object, so they must be represented as generic objects (e.g. RawJSON), but when we present the object as part of
61+
// API discovery we want to present the specific kind, not the generic internal representation.
62+
type KindProvider interface {
63+
Kind() string
64+
}
65+
5866
// Lister is an object that can retrieve resources that match the provided field and label criteria.
5967
type Lister interface {
6068
// NewList returns an empty object that can be used with the List call.

pkg/api/unversioned/types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ type APIResource struct {
339339
Name string `json:"name"`
340340
// namespaced indicates if a resource is namespaced or not.
341341
Namespaced bool `json:"namespaced"`
342+
// kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')
343+
Kind string `json:"kind"`
342344
}
343345

344346
// APIResourceList is a list of APIResource, it is used to expose the name of the

pkg/api/unversioned/types_swagger_doc_generated.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ var map_APIResource = map[string]string{
5151
"": "APIResource specifies the name of a resource and whether it is namespaced.",
5252
"name": "name is the name of the resource.",
5353
"namespaced": "namespaced indicates if a resource is namespaced or not.",
54+
"kind": "kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')",
5455
}
5556

5657
func (APIResource) SwaggerDoc() map[string]string {

pkg/apiserver/api_installer.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,11 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
152152
}
153153
}
154154

155+
kind := fqKindToRegister.Kind
156+
155157
if fqKindToRegister.IsEmpty() {
156158
return nil, fmt.Errorf("unable to locate fully qualified kind for %v: found %v when registering for %v", reflect.TypeOf(object), fqKinds, a.group.GroupVersion)
157159
}
158-
kind := fqKindToRegister.Kind
159160

160161
versionedPtr, err := a.group.Creater.New(a.group.GroupVersion.WithKind(kind))
161162
if err != nil {
@@ -322,6 +323,14 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
322323
params := []*restful.Parameter{}
323324
actions := []action{}
324325

326+
var resourceKind string
327+
kindProvider, ok := storage.(rest.KindProvider)
328+
if ok {
329+
resourceKind = kindProvider.Kind()
330+
} else {
331+
resourceKind = fqKindToRegister.Kind
332+
}
333+
325334
var apiResource unversioned.APIResource
326335
// Get the list of actions for the given scope.
327336
switch scope.Name() {
@@ -339,6 +348,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
339348
}
340349
apiResource.Name = path
341350
apiResource.Namespaced = false
351+
apiResource.Kind = resourceKind
342352
namer := rootScopeNaming{scope, a.group.Linker, gpath.Join(a.prefix, itemPath)}
343353

344354
// Handler for standard REST verbs (GET, PUT, POST and DELETE).
@@ -381,6 +391,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
381391
}
382392
apiResource.Name = path
383393
apiResource.Namespaced = true
394+
apiResource.Kind = resourceKind
384395
namer := scopeNaming{scope, a.group.Linker, gpath.Join(a.prefix, itemPath), false}
385396

386397
actions = appendIf(actions, action{"LIST", resourcePath, resourceParams, namer}, isLister)

pkg/client/unversioned/client_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,17 +137,17 @@ func TestGetServerResources(t *testing.T) {
137137
stable := unversioned.APIResourceList{
138138
GroupVersion: "v1",
139139
APIResources: []unversioned.APIResource{
140-
{"pods", true},
141-
{"services", true},
142-
{"namespaces", false},
140+
{"pods", true, "Pod"},
141+
{"services", true, "Service"},
142+
{"namespaces", false, "Namespace"},
143143
},
144144
}
145145
beta := unversioned.APIResourceList{
146146
GroupVersion: "extensions/v1",
147147
APIResources: []unversioned.APIResource{
148-
{"deployments", true},
149-
{"ingresses", true},
150-
{"jobs", true},
148+
{"deployments", true, "Deployment"},
149+
{"ingresses", true, "Ingress"},
150+
{"jobs", true, "Job"},
151151
},
152152
}
153153
tests := []struct {

pkg/registry/thirdpartyresourcedata/etcd/etcd.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
// REST implements a RESTStorage for ThirdPartyResourceDatas against etcd
3434
type REST struct {
3535
*etcdgeneric.Etcd
36+
kind string
3637
}
3738

3839
// NewREST returns a registry which will store ThirdPartyResourceData in the given helper
@@ -64,5 +65,13 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator, gro
6465
Storage: storageInterface,
6566
}
6667

67-
return &REST{store}
68+
return &REST{
69+
Etcd: store,
70+
kind: kind,
71+
}
72+
}
73+
74+
// Implements the rest.KindProvider interface
75+
func (r *REST) Kind() string {
76+
return r.kind
6877
}

0 commit comments

Comments
 (0)