remove rootscopedkinds from groupmeta
Kubernetes-commit: 8ae62517da5eff6d6bad21badfd39ee88463ad42
This commit is contained in:
parent
bd62696dfb
commit
b7f90743d0
|
@ -20,7 +20,6 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/apimachinery/announced"
|
"k8s.io/apimachinery/pkg/apimachinery/announced"
|
||||||
"k8s.io/apimachinery/pkg/apimachinery/registered"
|
"k8s.io/apimachinery/pkg/apimachinery/registered"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
|
||||||
"k8s.io/apiserver/pkg/apis/apiserver"
|
"k8s.io/apiserver/pkg/apis/apiserver"
|
||||||
"k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"
|
"k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"
|
||||||
)
|
)
|
||||||
|
@ -30,7 +29,6 @@ func Install(registry *registered.APIRegistrationManager, scheme *runtime.Scheme
|
||||||
if err := announced.NewGroupMetaFactory(
|
if err := announced.NewGroupMetaFactory(
|
||||||
&announced.GroupMetaFactoryArgs{
|
&announced.GroupMetaFactoryArgs{
|
||||||
GroupName: apiserver.GroupName,
|
GroupName: apiserver.GroupName,
|
||||||
RootScopedKinds: sets.NewString("AdmissionConfiguration"),
|
|
||||||
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version},
|
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version},
|
||||||
AddInternalObjectsToScheme: apiserver.AddToScheme,
|
AddInternalObjectsToScheme: apiserver.AddToScheme,
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/apimachinery/announced"
|
"k8s.io/apimachinery/pkg/apimachinery/announced"
|
||||||
"k8s.io/apimachinery/pkg/apimachinery/registered"
|
"k8s.io/apimachinery/pkg/apimachinery/registered"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
|
||||||
"k8s.io/apiserver/pkg/apis/audit"
|
"k8s.io/apiserver/pkg/apis/audit"
|
||||||
"k8s.io/apiserver/pkg/apis/audit/v1alpha1"
|
"k8s.io/apiserver/pkg/apis/audit/v1alpha1"
|
||||||
"k8s.io/apiserver/pkg/apis/audit/v1beta1"
|
"k8s.io/apiserver/pkg/apis/audit/v1beta1"
|
||||||
|
@ -32,10 +31,8 @@ import (
|
||||||
func Install(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) {
|
func Install(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) {
|
||||||
if err := announced.NewGroupMetaFactory(
|
if err := announced.NewGroupMetaFactory(
|
||||||
&announced.GroupMetaFactoryArgs{
|
&announced.GroupMetaFactoryArgs{
|
||||||
GroupName: audit.GroupName,
|
GroupName: audit.GroupName,
|
||||||
VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version, v1alpha1.SchemeGroupVersion.Version},
|
VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version, v1alpha1.SchemeGroupVersion.Version},
|
||||||
// Any Kind that is not namespaced must be cluster scoped.
|
|
||||||
RootScopedKinds: sets.NewString("Event", "Policy"),
|
|
||||||
AddInternalObjectsToScheme: audit.AddToScheme,
|
AddInternalObjectsToScheme: audit.AddToScheme,
|
||||||
},
|
},
|
||||||
announced.VersionToSchemeFunc{
|
announced.VersionToSchemeFunc{
|
||||||
|
|
|
@ -347,6 +347,10 @@ type SimpleRESTStorage struct {
|
||||||
injectedFunction func(obj runtime.Object) (returnObj runtime.Object, err error)
|
injectedFunction func(obj runtime.Object) (returnObj runtime.Object, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (storage *SimpleRESTStorage) NamespaceScoped() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (storage *SimpleRESTStorage) Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) {
|
func (storage *SimpleRESTStorage) Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) {
|
||||||
obj, err := storage.Get(ctx, name, &metav1.GetOptions{})
|
obj, err := storage.Get(ctx, name, &metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -615,6 +619,10 @@ type GetWithOptionsRootRESTStorage struct {
|
||||||
takesPath string
|
takesPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *GetWithOptionsRootRESTStorage) NamespaceScoped() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (r *GetWithOptionsRootRESTStorage) Get(ctx context.Context, name string, options runtime.Object) (runtime.Object, error) {
|
func (r *GetWithOptionsRootRESTStorage) Get(ctx context.Context, name string, options runtime.Object) (runtime.Object, error) {
|
||||||
if _, ok := options.(*genericapitesting.SimpleGetOptions); !ok {
|
if _, ok := options.(*genericapitesting.SimpleGetOptions); !ok {
|
||||||
return nil, fmt.Errorf("Unexpected options object: %#v", options)
|
return nil, fmt.Errorf("Unexpected options object: %#v", options)
|
||||||
|
@ -801,6 +809,10 @@ func TestNotFound(t *testing.T) {
|
||||||
|
|
||||||
type UnimplementedRESTStorage struct{}
|
type UnimplementedRESTStorage struct{}
|
||||||
|
|
||||||
|
func (UnimplementedRESTStorage) NamespaceScoped() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (UnimplementedRESTStorage) New() runtime.Object {
|
func (UnimplementedRESTStorage) New() runtime.Object {
|
||||||
return &genericapitesting.Simple{}
|
return &genericapitesting.Simple{}
|
||||||
}
|
}
|
||||||
|
@ -3774,10 +3786,6 @@ func (storage *SimpleXGSubresourceRESTStorage) GroupVersionKind(containingGV sch
|
||||||
return storage.itemGVK
|
return storage.itemGVK
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*SimpleXGSubresourceRESTStorage) ClusterScoped() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestXGSubresource(t *testing.T) {
|
func TestXGSubresource(t *testing.T) {
|
||||||
container := restful.NewContainer()
|
container := restful.NewContainer()
|
||||||
container.Router(restful.CurlyRouter{})
|
container.Router(restful.CurlyRouter{})
|
||||||
|
|
|
@ -132,18 +132,18 @@ func (a *APIInstaller) newWebService() *restful.WebService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getResourceKind returns the external group version kind registered for the given storage
|
// getResourceKind returns the external group version kind registered for the given storage
|
||||||
// object and whether or not the kind is cluster scoped. If the storage object is a subresource and has an override supplied for it, it returns
|
// object. If the storage object is a subresource and has an override supplied for it, it returns
|
||||||
// the group version kind supplied in the override.
|
// the group version kind supplied in the override.
|
||||||
func (a *APIInstaller) getResourceKind(path string, storage rest.Storage) (schema.GroupVersionKind, bool, error) {
|
func (a *APIInstaller) getResourceKind(path string, storage rest.Storage) (schema.GroupVersionKind, error) {
|
||||||
// Let the storage tell us exactly what GVK it has
|
// Let the storage tell us exactly what GVK it has
|
||||||
if gvkProvider, ok := storage.(rest.GroupVersionKindProvider); ok {
|
if gvkProvider, ok := storage.(rest.GroupVersionKindProvider); ok {
|
||||||
return gvkProvider.GroupVersionKind(a.group.GroupVersion), gvkProvider.ClusterScoped(), nil
|
return gvkProvider.GroupVersionKind(a.group.GroupVersion), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
object := storage.New()
|
object := storage.New()
|
||||||
fqKinds, _, err := a.group.Typer.ObjectKinds(object)
|
fqKinds, _, err := a.group.Typer.ObjectKinds(object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return schema.GroupVersionKind{}, false, err
|
return schema.GroupVersionKind{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// a given go type can have multiple potential fully qualified kinds. Find the one that corresponds with the group
|
// a given go type can have multiple potential fully qualified kinds. Find the one that corresponds with the group
|
||||||
|
@ -156,11 +156,11 @@ func (a *APIInstaller) getResourceKind(path string, storage rest.Storage) (schem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fqKindToRegister.Empty() {
|
if fqKindToRegister.Empty() {
|
||||||
return schema.GroupVersionKind{}, false, fmt.Errorf("unable to locate fully qualified kind for %v: found %v when registering for %v", reflect.TypeOf(object), fqKinds, a.group.GroupVersion)
|
return schema.GroupVersionKind{}, fmt.Errorf("unable to locate fully qualified kind for %v: found %v when registering for %v", reflect.TypeOf(object), fqKinds, a.group.GroupVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// group is guaranteed to match based on the check above
|
// group is guaranteed to match based on the check above
|
||||||
return fqKindToRegister, a.group.RootScopedKinds.Has(fqKindToRegister.Kind), nil
|
return fqKindToRegister, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storage, ws *restful.WebService) (*metav1.APIResource, error) {
|
func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storage, ws *restful.WebService) (*metav1.APIResource, error) {
|
||||||
|
@ -176,7 +176,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fqKindToRegister, clusterScoped, err := a.getResourceKind(path, storage)
|
fqKindToRegister, err := a.getResourceKind(path, storage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,28 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
}
|
}
|
||||||
defaultVersionedObject := indirectArbitraryPointer(versionedPtr)
|
defaultVersionedObject := indirectArbitraryPointer(versionedPtr)
|
||||||
kind := fqKindToRegister.Kind
|
kind := fqKindToRegister.Kind
|
||||||
hasSubresource := len(subresource) > 0
|
isSubresource := len(subresource) > 0
|
||||||
|
|
||||||
|
// If there is a subresource, namespace scoping is defined by the parent resource
|
||||||
|
namespaceScoped := true
|
||||||
|
if isSubresource {
|
||||||
|
parentStorage, ok := a.group.Storage[resource]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("missing parent storage: %q", resource)
|
||||||
|
}
|
||||||
|
scoper, ok := parentStorage.(rest.Scoper)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("%q must implement scoper", resource)
|
||||||
|
}
|
||||||
|
namespaceScoped = scoper.NamespaceScoped()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
scoper, ok := storage.(rest.Scoper)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("%q must implement scoper", resource)
|
||||||
|
}
|
||||||
|
namespaceScoped = scoper.NamespaceScoped()
|
||||||
|
}
|
||||||
|
|
||||||
// what verbs are supported by the storage, used to know what verbs we support per path
|
// what verbs are supported by the storage, used to know what verbs we support per path
|
||||||
creater, isCreater := storage.(rest.Creater)
|
creater, isCreater := storage.(rest.Creater)
|
||||||
|
@ -330,7 +351,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
var apiResource metav1.APIResource
|
var apiResource metav1.APIResource
|
||||||
// Get the list of actions for the given scope.
|
// Get the list of actions for the given scope.
|
||||||
switch {
|
switch {
|
||||||
case clusterScoped:
|
case !namespaceScoped:
|
||||||
// Handle non-namespace scoped resources like nodes.
|
// Handle non-namespace scoped resources like nodes.
|
||||||
resourcePath := resource
|
resourcePath := resource
|
||||||
resourceParams := params
|
resourceParams := params
|
||||||
|
@ -338,7 +359,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
nameParams := append(params, nameParam)
|
nameParams := append(params, nameParam)
|
||||||
proxyParams := append(nameParams, pathParam)
|
proxyParams := append(nameParams, pathParam)
|
||||||
suffix := ""
|
suffix := ""
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
suffix = "/" + subresource
|
suffix = "/" + subresource
|
||||||
itemPath = itemPath + suffix
|
itemPath = itemPath + suffix
|
||||||
resourcePath = itemPath
|
resourcePath = itemPath
|
||||||
|
@ -387,7 +408,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
nameParams := append(namespaceParams, nameParam)
|
nameParams := append(namespaceParams, nameParam)
|
||||||
proxyParams := append(nameParams, pathParam)
|
proxyParams := append(nameParams, pathParam)
|
||||||
itemPathSuffix := ""
|
itemPathSuffix := ""
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
itemPathSuffix = "/" + subresource
|
itemPathSuffix = "/" + subresource
|
||||||
itemPath = itemPath + itemPathSuffix
|
itemPath = itemPath + itemPathSuffix
|
||||||
resourcePath = itemPath
|
resourcePath = itemPath
|
||||||
|
@ -423,7 +444,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
// list or post across namespace.
|
// list or post across namespace.
|
||||||
// For ex: LIST all pods in all namespaces by sending a LIST request at /api/apiVersion/pods.
|
// For ex: LIST all pods in all namespaces by sending a LIST request at /api/apiVersion/pods.
|
||||||
// TODO: more strongly type whether a resource allows these actions on "all namespaces" (bulk delete)
|
// TODO: more strongly type whether a resource allows these actions on "all namespaces" (bulk delete)
|
||||||
if !hasSubresource {
|
if !isSubresource {
|
||||||
actions = appendIf(actions, action{"LIST", resource, params, namer, true}, isLister)
|
actions = appendIf(actions, action{"LIST", resource, params, namer, true}, isLister)
|
||||||
actions = appendIf(actions, action{"WATCHLIST", "watch/" + resource, params, namer, true}, allowWatchList)
|
actions = appendIf(actions, action{"WATCHLIST", "watch/" + resource, params, namer, true}, allowWatchList)
|
||||||
}
|
}
|
||||||
|
@ -509,12 +530,13 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
routes := []*restful.RouteBuilder{}
|
routes := []*restful.RouteBuilder{}
|
||||||
|
|
||||||
// If there is a subresource, kind should be the parent's kind.
|
// If there is a subresource, kind should be the parent's kind.
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
parentStorage, ok := a.group.Storage[resource]
|
parentStorage, ok := a.group.Storage[resource]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing parent storage: %q", resource)
|
return nil, fmt.Errorf("missing parent storage: %q", resource)
|
||||||
}
|
}
|
||||||
fqParentKind, _, err := a.getResourceKind(resource, parentStorage)
|
|
||||||
|
fqParentKind, err := a.getResourceKind(resource, parentStorage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -527,7 +549,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
case "GET": // Get a resource.
|
case "GET": // Get a resource.
|
||||||
var handler restful.RouteFunction
|
var handler restful.RouteFunction
|
||||||
if isGetterWithOptions {
|
if isGetterWithOptions {
|
||||||
handler = restfulGetResourceWithOptions(getterWithOptions, reqScope, hasSubresource)
|
handler = restfulGetResourceWithOptions(getterWithOptions, reqScope, isSubresource)
|
||||||
} else {
|
} else {
|
||||||
handler = restfulGetResource(getter, exporter, reqScope)
|
handler = restfulGetResource(getter, exporter, reqScope)
|
||||||
}
|
}
|
||||||
|
@ -543,7 +565,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
handler = genericfilters.RestfulWithCompression(handler)
|
handler = genericfilters.RestfulWithCompression(handler)
|
||||||
}
|
}
|
||||||
doc := "read the specified " + kind
|
doc := "read the specified " + kind
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
doc = "read " + subresource + " of the specified " + kind
|
doc = "read " + subresource + " of the specified " + kind
|
||||||
}
|
}
|
||||||
route := ws.GET(action.Path).To(handler).
|
route := ws.GET(action.Path).To(handler).
|
||||||
|
@ -567,7 +589,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
routes = append(routes, route)
|
routes = append(routes, route)
|
||||||
case "LIST": // List all resources of a kind.
|
case "LIST": // List all resources of a kind.
|
||||||
doc := "list objects of kind " + kind
|
doc := "list objects of kind " + kind
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
doc = "list " + subresource + " of objects of kind " + kind
|
doc = "list " + subresource + " of objects of kind " + kind
|
||||||
}
|
}
|
||||||
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulListResource(lister, watcher, reqScope, false, a.minRequestTimeout))
|
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulListResource(lister, watcher, reqScope, false, a.minRequestTimeout))
|
||||||
|
@ -587,13 +609,13 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
switch {
|
switch {
|
||||||
case isLister && isWatcher:
|
case isLister && isWatcher:
|
||||||
doc := "list or watch objects of kind " + kind
|
doc := "list or watch objects of kind " + kind
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
doc = "list or watch " + subresource + " of objects of kind " + kind
|
doc = "list or watch " + subresource + " of objects of kind " + kind
|
||||||
}
|
}
|
||||||
route.Doc(doc)
|
route.Doc(doc)
|
||||||
case isWatcher:
|
case isWatcher:
|
||||||
doc := "watch objects of kind " + kind
|
doc := "watch objects of kind " + kind
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
doc = "watch " + subresource + "of objects of kind " + kind
|
doc = "watch " + subresource + "of objects of kind " + kind
|
||||||
}
|
}
|
||||||
route.Doc(doc)
|
route.Doc(doc)
|
||||||
|
@ -602,7 +624,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
routes = append(routes, route)
|
routes = append(routes, route)
|
||||||
case "PUT": // Update a resource.
|
case "PUT": // Update a resource.
|
||||||
doc := "replace the specified " + kind
|
doc := "replace the specified " + kind
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
doc = "replace " + subresource + " of the specified " + kind
|
doc = "replace " + subresource + " of the specified " + kind
|
||||||
}
|
}
|
||||||
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulUpdateResource(updater, reqScope, admit))
|
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulUpdateResource(updater, reqScope, admit))
|
||||||
|
@ -621,7 +643,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
routes = append(routes, route)
|
routes = append(routes, route)
|
||||||
case "PATCH": // Partially update a resource
|
case "PATCH": // Partially update a resource
|
||||||
doc := "partially update the specified " + kind
|
doc := "partially update the specified " + kind
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
doc = "partially update " + subresource + " of the specified " + kind
|
doc = "partially update " + subresource + " of the specified " + kind
|
||||||
}
|
}
|
||||||
supportedTypes := []string{
|
supportedTypes := []string{
|
||||||
|
@ -651,7 +673,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
handler = metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, handler)
|
handler = metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, handler)
|
||||||
article := getArticleForNoun(kind, " ")
|
article := getArticleForNoun(kind, " ")
|
||||||
doc := "create" + article + kind
|
doc := "create" + article + kind
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
doc = "create " + subresource + " of" + article + kind
|
doc = "create " + subresource + " of" + article + kind
|
||||||
}
|
}
|
||||||
route := ws.POST(action.Path).To(handler).
|
route := ws.POST(action.Path).To(handler).
|
||||||
|
@ -671,7 +693,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
case "DELETE": // Delete a resource.
|
case "DELETE": // Delete a resource.
|
||||||
article := getArticleForNoun(kind, " ")
|
article := getArticleForNoun(kind, " ")
|
||||||
doc := "delete" + article + kind
|
doc := "delete" + article + kind
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
doc = "delete " + subresource + " of" + article + kind
|
doc = "delete " + subresource + " of" + article + kind
|
||||||
}
|
}
|
||||||
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulDeleteResource(gracefulDeleter, isGracefulDeleter, reqScope, admit))
|
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulDeleteResource(gracefulDeleter, isGracefulDeleter, reqScope, admit))
|
||||||
|
@ -692,7 +714,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
routes = append(routes, route)
|
routes = append(routes, route)
|
||||||
case "DELETECOLLECTION":
|
case "DELETECOLLECTION":
|
||||||
doc := "delete collection of " + kind
|
doc := "delete collection of " + kind
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
doc = "delete collection of " + subresource + " of a " + kind
|
doc = "delete collection of " + subresource + " of a " + kind
|
||||||
}
|
}
|
||||||
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulDeleteCollection(collectionDeleter, isCollectionDeleter, reqScope, admit))
|
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulDeleteCollection(collectionDeleter, isCollectionDeleter, reqScope, admit))
|
||||||
|
@ -711,7 +733,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
// TODO: deprecated
|
// TODO: deprecated
|
||||||
case "WATCH": // Watch a resource.
|
case "WATCH": // Watch a resource.
|
||||||
doc := "watch changes to an object of kind " + kind
|
doc := "watch changes to an object of kind " + kind
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
doc = "watch changes to " + subresource + " of an object of kind " + kind
|
doc = "watch changes to " + subresource + " of an object of kind " + kind
|
||||||
}
|
}
|
||||||
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout))
|
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout))
|
||||||
|
@ -730,7 +752,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
// TODO: deprecated
|
// TODO: deprecated
|
||||||
case "WATCHLIST": // Watch all resources of a kind.
|
case "WATCHLIST": // Watch all resources of a kind.
|
||||||
doc := "watch individual changes to a list of " + kind
|
doc := "watch individual changes to a list of " + kind
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
doc = "watch individual changes to a list of " + subresource + " of " + kind
|
doc = "watch individual changes to a list of " + subresource + " of " + kind
|
||||||
}
|
}
|
||||||
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout))
|
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout))
|
||||||
|
@ -753,10 +775,10 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
connectProducedObject = "string"
|
connectProducedObject = "string"
|
||||||
}
|
}
|
||||||
doc := "connect " + method + " requests to " + kind
|
doc := "connect " + method + " requests to " + kind
|
||||||
if hasSubresource {
|
if isSubresource {
|
||||||
doc = "connect " + method + " requests to " + subresource + " of " + kind
|
doc = "connect " + method + " requests to " + subresource + " of " + kind
|
||||||
}
|
}
|
||||||
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulConnectResource(connecter, reqScope, admit, path, hasSubresource))
|
handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulConnectResource(connecter, reqScope, admit, path, isSubresource))
|
||||||
route := ws.Method(method).Path(action.Path).
|
route := ws.Method(method).Path(action.Path).
|
||||||
To(handler).
|
To(handler).
|
||||||
Doc(doc).
|
Doc(doc).
|
||||||
|
|
|
@ -242,6 +242,18 @@ func (e *Store) NewList() runtime.Object {
|
||||||
return e.NewListFunc()
|
return e.NewListFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NamespaceScoped indicates whether the resource is namespaced
|
||||||
|
func (e *Store) NamespaceScoped() bool {
|
||||||
|
if e.CreateStrategy != nil {
|
||||||
|
return e.CreateStrategy.NamespaceScoped()
|
||||||
|
}
|
||||||
|
if e.UpdateStrategy != nil {
|
||||||
|
return e.UpdateStrategy.NamespaceScoped()
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("programmer error: no CRUD for resource, you're crazy, override NamespaceScoped too")
|
||||||
|
}
|
||||||
|
|
||||||
// GetCreateStrategy implements GenericStore.
|
// GetCreateStrategy implements GenericStore.
|
||||||
func (e *Store) GetCreateStrategy() rest.RESTCreateStrategy {
|
func (e *Store) GetCreateStrategy() rest.RESTCreateStrategy {
|
||||||
return e.CreateStrategy
|
return e.CreateStrategy
|
||||||
|
|
|
@ -58,6 +58,13 @@ type Storage interface {
|
||||||
New() runtime.Object
|
New() runtime.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scoper indicates what scope the resource is at. It must be specified.
|
||||||
|
// It is usually provided automatically based on your strategy.
|
||||||
|
type Scoper interface {
|
||||||
|
// NamespaceScoped returns true if the storage is namespaced
|
||||||
|
NamespaceScoped() bool
|
||||||
|
}
|
||||||
|
|
||||||
// KindProvider specifies a different kind for its API than for its internal storage. This is necessary for external
|
// KindProvider specifies a different kind for its API than for its internal storage. This is necessary for external
|
||||||
// objects that are not compiled into the api server. For such objects, there is no in-memory representation for
|
// objects that are not compiled into the api server. For such objects, there is no in-memory representation for
|
||||||
// the object, so they must be represented as generic objects (e.g. runtime.Unknown), but when we present the object as part of
|
// the object, so they must be represented as generic objects (e.g. runtime.Unknown), but when we present the object as part of
|
||||||
|
@ -83,7 +90,6 @@ type CategoriesProvider interface {
|
||||||
// TODO KindProvider (only used by federation) should be removed and replaced with this, but that presents greater risk late in 1.8.
|
// TODO KindProvider (only used by federation) should be removed and replaced with this, but that presents greater risk late in 1.8.
|
||||||
type GroupVersionKindProvider interface {
|
type GroupVersionKindProvider interface {
|
||||||
GroupVersionKind(containingGV schema.GroupVersion) schema.GroupVersionKind
|
GroupVersionKind(containingGV schema.GroupVersion) schema.GroupVersionKind
|
||||||
ClusterScoped() bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lister is an object that can retrieve resources that match the provided field and label criteria.
|
// Lister is an object that can retrieve resources that match the provided field and label criteria.
|
||||||
|
|
|
@ -424,7 +424,6 @@ func (s *GenericAPIServer) newAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupV
|
||||||
Defaulter: apiGroupInfo.Scheme,
|
Defaulter: apiGroupInfo.Scheme,
|
||||||
Typer: apiGroupInfo.Scheme,
|
Typer: apiGroupInfo.Scheme,
|
||||||
Linker: runtime.SelfLinker(meta.NewAccessor()),
|
Linker: runtime.SelfLinker(meta.NewAccessor()),
|
||||||
RootScopedKinds: apiGroupInfo.GroupMeta.RootScopedKinds,
|
|
||||||
|
|
||||||
Admit: s.admissionControl,
|
Admit: s.admissionControl,
|
||||||
MinRequestTimeout: s.minRequestTimeout,
|
MinRequestTimeout: s.minRequestTimeout,
|
||||||
|
|
|
@ -43,7 +43,6 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/version"
|
"k8s.io/apimachinery/pkg/version"
|
||||||
"k8s.io/apiserver/pkg/apis/example"
|
"k8s.io/apiserver/pkg/apis/example"
|
||||||
examplev1 "k8s.io/apiserver/pkg/apis/example/v1"
|
examplev1 "k8s.io/apiserver/pkg/apis/example/v1"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/apiserver/pkg/endpoints/discovery"
|
"k8s.io/apiserver/pkg/endpoints/discovery"
|
||||||
genericapifilters "k8s.io/apiserver/pkg/endpoints/filters"
|
genericapifilters "k8s.io/apiserver/pkg/endpoints/filters"
|
||||||
|
@ -416,34 +415,14 @@ func (authz *mockAuthorizer) Authorize(a authorizer.Attributes) (authorized auth
|
||||||
return authorizer.DecisionAllow, "", nil
|
return authorizer.DecisionAllow, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockAuthenticator struct {
|
|
||||||
lastURI string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (authn *mockAuthenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
|
|
||||||
authn.lastURI = req.RequestURI
|
|
||||||
return &user.DefaultInfo{
|
|
||||||
Name: "foo",
|
|
||||||
}, true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeResponse(resp *http.Response, obj interface{}) error {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(data, obj); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type testGetterStorage struct {
|
type testGetterStorage struct {
|
||||||
Version string
|
Version string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *testGetterStorage) NamespaceScoped() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (p *testGetterStorage) New() runtime.Object {
|
func (p *testGetterStorage) New() runtime.Object {
|
||||||
return &metav1.APIGroup{
|
return &metav1.APIGroup{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
@ -461,6 +440,10 @@ type testNoVerbsStorage struct {
|
||||||
Version string
|
Version string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *testNoVerbsStorage) NamespaceScoped() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (p *testNoVerbsStorage) New() runtime.Object {
|
func (p *testNoVerbsStorage) New() runtime.Object {
|
||||||
return &metav1.APIGroup{
|
return &metav1.APIGroup{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
|
Loading…
Reference in New Issue