diff --git a/cmd/kubernetes-discovery/pkg/apiserver/BUILD b/cmd/kubernetes-discovery/pkg/apiserver/BUILD index f1dacc1fa5..3465ab3d07 100644 --- a/cmd/kubernetes-discovery/pkg/apiserver/BUILD +++ b/cmd/kubernetes-discovery/pkg/apiserver/BUILD @@ -26,7 +26,7 @@ go_library( "//cmd/kubernetes-discovery/pkg/client/informers:go_default_library", "//cmd/kubernetes-discovery/pkg/client/informers/apiregistration/internalversion:go_default_library", "//cmd/kubernetes-discovery/pkg/client/listers/apiregistration/internalversion:go_default_library", - "//cmd/kubernetes-discovery/pkg/registry/apiservice:go_default_library", + "//cmd/kubernetes-discovery/pkg/registry/apiservice/etcd:go_default_library", "//pkg/api:go_default_library", "//pkg/api/errors:go_default_library", "//pkg/api/rest:go_default_library", @@ -41,7 +41,6 @@ go_library( "//pkg/labels:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/runtime/schema:go_default_library", "//pkg/util/runtime:go_default_library", "//pkg/util/sets:go_default_library", "//pkg/util/wait:go_default_library", diff --git a/cmd/kubernetes-discovery/pkg/apiserver/apiserver.go b/cmd/kubernetes-discovery/pkg/apiserver/apiserver.go index c211251a32..84fb84edf3 100644 --- a/cmd/kubernetes-discovery/pkg/apiserver/apiserver.go +++ b/cmd/kubernetes-discovery/pkg/apiserver/apiserver.go @@ -28,7 +28,6 @@ import ( "k8s.io/kubernetes/pkg/genericapiserver" genericfilters "k8s.io/kubernetes/pkg/genericapiserver/filters" "k8s.io/kubernetes/pkg/registry/generic" - "k8s.io/kubernetes/pkg/runtime/schema" "k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/wait" "k8s.io/kubernetes/pkg/version" @@ -39,23 +38,17 @@ import ( clientset "k8s.io/kubernetes/cmd/kubernetes-discovery/pkg/client/clientset_generated/release_1_5" "k8s.io/kubernetes/cmd/kubernetes-discovery/pkg/client/informers" listers "k8s.io/kubernetes/cmd/kubernetes-discovery/pkg/client/listers/apiregistration/internalversion" - apiservicestorage "k8s.io/kubernetes/cmd/kubernetes-discovery/pkg/registry/apiservice" + apiservicestorage "k8s.io/kubernetes/cmd/kubernetes-discovery/pkg/registry/apiservice/etcd" ) // legacyAPIServiceName is the fixed name of the only non-groupified API version const legacyAPIServiceName = "v1." -// TODO move to genericapiserver or something like that -// RESTOptionsGetter is used to construct storage for a particular resource -type RESTOptionsGetter interface { - NewFor(resource schema.GroupResource) generic.RESTOptions -} - type Config struct { GenericConfig *genericapiserver.Config // RESTOptionsGetter is used to construct storage for a particular resource - RESTOptionsGetter RESTOptionsGetter + RESTOptionsGetter generic.RESTOptionsGetter } // APIDiscoveryServer contains state for a Kubernetes cluster master/api server. @@ -117,7 +110,7 @@ func (c completedConfig) New() (*APIDiscoveryServer, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiregistration.GroupName) apiGroupInfo.GroupMeta.GroupVersion = v1alpha1.SchemeGroupVersion v1alpha1storage := map[string]rest.Storage{} - v1alpha1storage["apiservices"] = apiservicestorage.NewREST(c.RESTOptionsGetter.NewFor(apiregistration.Resource("apiservices"))) + v1alpha1storage["apiservices"] = apiservicestorage.NewREST(c.RESTOptionsGetter) apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil { diff --git a/cmd/kubernetes-discovery/pkg/cmd/server/start.go b/cmd/kubernetes-discovery/pkg/cmd/server/start.go index 7ef9717550..b2b806accd 100644 --- a/cmd/kubernetes-discovery/pkg/cmd/server/start.go +++ b/cmd/kubernetes-discovery/pkg/cmd/server/start.go @@ -122,7 +122,7 @@ func (o DiscoveryServerOptions) RunDiscoveryServer() error { config := apiserver.Config{ GenericConfig: genericAPIServerConfig, - RESTOptionsGetter: restOptionsFactory{storageConfig: &o.Etcd.StorageConfig}, + RESTOptionsGetter: &restOptionsFactory{storageConfig: &o.Etcd.StorageConfig}, } server, err := config.Complete().New() @@ -149,12 +149,12 @@ type restOptionsFactory struct { storageConfig *storagebackend.Config } -func (f restOptionsFactory) NewFor(resource schema.GroupResource) generic.RESTOptions { +func (f *restOptionsFactory) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) { return generic.RESTOptions{ StorageConfig: f.storageConfig, Decorator: registry.StorageWithCacher, DeleteCollectionWorkers: 1, EnableGarbageCollection: false, ResourcePrefix: f.storageConfig.Prefix + "/" + resource.Group + "/" + resource.Resource, - } + }, nil } diff --git a/cmd/kubernetes-discovery/pkg/registry/apiservice/BUILD b/cmd/kubernetes-discovery/pkg/registry/apiservice/BUILD index 1452e833ca..77ebf867df 100644 --- a/cmd/kubernetes-discovery/pkg/registry/apiservice/BUILD +++ b/cmd/kubernetes-discovery/pkg/registry/apiservice/BUILD @@ -12,10 +12,7 @@ load( go_library( name = "go_default_library", - srcs = [ - "etcd.go", - "strategy.go", - ], + srcs = ["strategy.go"], tags = ["automanaged"], deps = [ "//cmd/kubernetes-discovery/pkg/apis/apiregistration:go_default_library", @@ -24,7 +21,6 @@ go_library( "//pkg/fields:go_default_library", "//pkg/labels:go_default_library", "//pkg/registry/generic:go_default_library", - "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", "//pkg/storage:go_default_library", "//pkg/util/validation/field:go_default_library", diff --git a/cmd/kubernetes-discovery/pkg/registry/apiservice/etcd.go b/cmd/kubernetes-discovery/pkg/registry/apiservice/etcd.go deleted file mode 100644 index 0943ecf0d8..0000000000 --- a/cmd/kubernetes-discovery/pkg/registry/apiservice/etcd.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright 2016 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 apiservice - -import ( - "fmt" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/registry/generic" - "k8s.io/kubernetes/pkg/registry/generic/registry" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" - - "k8s.io/kubernetes/cmd/kubernetes-discovery/pkg/apis/apiregistration" -) - -// rest implements a RESTStorage for network policies against etcd -type REST struct { - *registry.Store -} - -// NewREST returns a RESTStorage object that will work against network policies. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &apiregistration.APIServiceList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - 1000, // cache size - &apiregistration.APIService{}, - prefix, - strategy, - newListFunc, - getAttrs, - storage.NoTriggerPublisher, - ) - - store := ®istry.Store{ - NewFunc: func() runtime.Object { return &apiregistration.APIService{} }, - - // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a APIService that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix - KeyRootFunc: func(ctx api.Context) string { - return prefix - }, - // Produces a APIService that etcd understands, to the resource by combining - // the namespace in the context with the given prefix - KeyFunc: func(ctx api.Context, name string) (string, error) { - return registry.NoNamespaceKeyFunc(ctx, prefix, name) - }, - // Retrieve the name field of an apiserver - ObjectNameFunc: func(obj runtime.Object) (string, error) { - return obj.(*apiregistration.APIService).Name, nil - }, - // Used to match objects based on labels/fields for list and watch - PredicateFunc: MatchAPIService, - QualifiedResource: apiregistration.Resource("apiservers"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, - - // Used to validate controller creation - CreateStrategy: strategy, - - // Used to validate controller updates - UpdateStrategy: strategy, - DeleteStrategy: strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, - } - return &REST{store} -} - -// getAttrs returns labels and fields of a given object for filtering purposes. -func getAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { - castObj, ok := obj.(*apiregistration.APIService) - if !ok { - return nil, nil, fmt.Errorf("given object is not an APIService.") - } - return labels.Set(castObj.ObjectMeta.Labels), APIServiceToSelectableFields(castObj), nil -} diff --git a/cmd/kubernetes-discovery/pkg/registry/apiservice/etcd/BUILD b/cmd/kubernetes-discovery/pkg/registry/apiservice/etcd/BUILD new file mode 100644 index 0000000000..225ce1f8ad --- /dev/null +++ b/cmd/kubernetes-discovery/pkg/registry/apiservice/etcd/BUILD @@ -0,0 +1,24 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_binary", + "go_library", + "go_test", + "cgo_library", +) + +go_library( + name = "go_default_library", + srcs = ["etcd.go"], + tags = ["automanaged"], + deps = [ + "//cmd/kubernetes-discovery/pkg/apis/apiregistration:go_default_library", + "//cmd/kubernetes-discovery/pkg/registry/apiservice:go_default_library", + "//pkg/registry/generic:go_default_library", + "//pkg/registry/generic/registry:go_default_library", + "//pkg/runtime:go_default_library", + ], +) diff --git a/cmd/kubernetes-discovery/pkg/registry/apiservice/etcd/etcd.go b/cmd/kubernetes-discovery/pkg/registry/apiservice/etcd/etcd.go new file mode 100644 index 0000000000..2bbb96f540 --- /dev/null +++ b/cmd/kubernetes-discovery/pkg/registry/apiservice/etcd/etcd.go @@ -0,0 +1,52 @@ +/* +Copyright 2016 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 etcd + +import ( + "k8s.io/kubernetes/cmd/kubernetes-discovery/pkg/apis/apiregistration" + "k8s.io/kubernetes/cmd/kubernetes-discovery/pkg/registry/apiservice" + "k8s.io/kubernetes/pkg/registry/generic" + genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" + "k8s.io/kubernetes/pkg/runtime" +) + +// rest implements a RESTStorage for API services against etcd +type REST struct { + *genericregistry.Store +} + +// NewREST returns a RESTStorage object that will work against API services. +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { + store := &genericregistry.Store{ + NewFunc: func() runtime.Object { return &apiregistration.APIService{} }, + NewListFunc: func() runtime.Object { return &apiregistration.APIServiceList{} }, + ObjectNameFunc: func(obj runtime.Object) (string, error) { + return obj.(*apiregistration.APIService).Name, nil + }, + PredicateFunc: apiservice.MatchAPIService, + QualifiedResource: apiregistration.Resource("apiservices"), + + CreateStrategy: apiservice.Strategy, + UpdateStrategy: apiservice.Strategy, + DeleteStrategy: apiservice.Strategy, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: apiservice.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up + } + return &REST{store} +} diff --git a/cmd/kubernetes-discovery/pkg/registry/apiservice/strategy.go b/cmd/kubernetes-discovery/pkg/registry/apiservice/strategy.go index a04c7a0d03..89fa671f75 100644 --- a/cmd/kubernetes-discovery/pkg/registry/apiservice/strategy.go +++ b/cmd/kubernetes-discovery/pkg/registry/apiservice/strategy.go @@ -36,7 +36,7 @@ type apiServerStrategy struct { kapi.NameGenerator } -var strategy = apiServerStrategy{kapi.Scheme, kapi.SimpleNameGenerator} +var Strategy = apiServerStrategy{kapi.Scheme, kapi.SimpleNameGenerator} func (apiServerStrategy) NamespaceScoped() bool { return false @@ -71,19 +71,21 @@ func (apiServerStrategy) ValidateUpdate(ctx kapi.Context, obj, old runtime.Objec return validation.ValidateAPIServiceUpdate(obj.(*apiregistration.APIService), old.(*apiregistration.APIService)) } +func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { + apiserver, ok := obj.(*apiregistration.APIService) + if !ok { + return nil, nil, fmt.Errorf("given object is not a APIService.") + } + return labels.Set(apiserver.ObjectMeta.Labels), APIServiceToSelectableFields(apiserver), nil +} + // MatchAPIService is the filter used by the generic etcd backend to watch events // from etcd to clients of the apiserver only interested in specific labels/fields. func MatchAPIService(label labels.Selector, field fields.Selector) storage.SelectionPredicate { return storage.SelectionPredicate{ - Label: label, - Field: field, - GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) { - apiserver, ok := obj.(*apiregistration.APIService) - if !ok { - return nil, nil, fmt.Errorf("given object is not a APIService.") - } - return labels.Set(apiserver.ObjectMeta.Labels), APIServiceToSelectableFields(apiserver), nil - }, + Label: label, + Field: field, + GetAttrs: GetAttrs, } } diff --git a/examples/apiserver/apiserver.go b/examples/apiserver/apiserver.go index 5442a6f1d1..ddfdec5e29 100644 --- a/examples/apiserver/apiserver.go +++ b/examples/apiserver/apiserver.go @@ -128,8 +128,15 @@ func (serverOptions *ServerRunOptions) Run(stopCh <-chan struct{}) error { return fmt.Errorf("Unable to get storage config: %v", err) } + testTypeOpts := generic.RESTOptions{ + StorageConfig: storageConfig, + Decorator: generic.UndecoratedStorage, + ResourcePrefix: "testtypes", + DeleteCollectionWorkers: 1, + } + restStorageMap := map[string]rest.Storage{ - "testtypes": testgroupetcd.NewREST(storageConfig, generic.UndecoratedStorage), + "testtypes": testgroupetcd.NewREST(testTypeOpts), } apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *groupMeta, diff --git a/examples/apiserver/rest/reststorage.go b/examples/apiserver/rest/reststorage.go index 3d8ced15c6..00e2742993 100644 --- a/examples/apiserver/rest/reststorage.go +++ b/examples/apiserver/rest/reststorage.go @@ -27,7 +27,7 @@ import ( genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/storage" - "k8s.io/kubernetes/pkg/storage/storagebackend" + "k8s.io/kubernetes/pkg/util/validation/field" ) type REST struct { @@ -35,60 +35,53 @@ type REST struct { } // NewREST returns a RESTStorage object that will work with testtype. -func NewREST(config *storagebackend.Config, storageDecorator generic.StorageDecorator) *REST { - prefix := "/testtype" - newListFunc := func() runtime.Object { return &testgroup.TestTypeList{} } - // Usually you should reuse your RESTCreateStrategy. - strategy := &NotNamespaceScoped{} - getAttrs := func(obj runtime.Object) (labels.Set, fields.Set, error) { - testObj, ok := obj.(*testgroup.TestType) - if !ok { - return nil, nil, fmt.Errorf("not a TestType") - } - return labels.Set(testObj.Labels), nil, nil - } - storageInterface, _ := storageDecorator( - config, 100, &testgroup.TestType{}, prefix, strategy, newListFunc, getAttrs, storage.NoTriggerPublisher) +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &testgroup.TestType{} }, // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a path that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix. - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - // Produces a path that etcd understands, to the resource by combining - // the namespace in the context with the given prefix. - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &testgroup.TestTypeList{} }, // Retrieve the name field of the resource. ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*testgroup.TestType).Name, nil }, // Used to match objects based on labels/fields for list. - PredicateFunc: func(label labels.Selector, field fields.Selector) storage.SelectionPredicate { - return storage.SelectionPredicate{ - Label: label, - Field: field, - GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) { - testType, ok := obj.(*testgroup.TestType) - if !ok { - return nil, nil, fmt.Errorf("unexpected type of given object") - } - return labels.Set(testType.ObjectMeta.Labels), fields.Set{}, nil - }, - } - }, - Storage: storageInterface, + PredicateFunc: matcher, + // QualifiedResource should always be plural + QualifiedResource: api.Resource("testtypes"), + + CreateStrategy: strategy, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: getAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} } -type NotNamespaceScoped struct { +type fakeStrategy struct { + runtime.ObjectTyper + api.NameGenerator } -func (*NotNamespaceScoped) NamespaceScoped() bool { - return false +func (*fakeStrategy) NamespaceScoped() bool { return false } +func (*fakeStrategy) PrepareForCreate(ctx api.Context, obj runtime.Object) {} +func (*fakeStrategy) Validate(ctx api.Context, obj runtime.Object) field.ErrorList { return nil } +func (*fakeStrategy) Canonicalize(obj runtime.Object) {} + +var strategy = &fakeStrategy{api.Scheme, api.SimpleNameGenerator} + +func getAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { + testType, ok := obj.(*testgroup.TestType) + if !ok { + return nil, nil, fmt.Errorf("not a TestType") + } + return labels.Set(testType.ObjectMeta.Labels), fields.Set{}, nil +} + +func matcher(label labels.Selector, field fields.Selector) storage.SelectionPredicate { + return storage.SelectionPredicate{ + Label: label, + Field: field, + GetAttrs: getAttrs, + } } diff --git a/examples/apiserver/server/main.go b/examples/apiserver/server/main.go index 5dff01318a..6dd94f3006 100644 --- a/examples/apiserver/server/main.go +++ b/examples/apiserver/server/main.go @@ -29,7 +29,7 @@ func main() { serverRunOptions := apiserver.NewServerRunOptions() // Parse command line flags. - serverRunOptions.AddUniversalFlags(pflag.CommandLine) + serverRunOptions.GenericServerRunOptions.AddUniversalFlags(pflag.CommandLine) serverRunOptions.Etcd.AddFlags(pflag.CommandLine) serverRunOptions.SecureServing.AddFlags(pflag.CommandLine) serverRunOptions.SecureServing.AddDeprecatedFlags(pflag.CommandLine) diff --git a/federation/cmd/federation-apiserver/app/core.go b/federation/cmd/federation-apiserver/app/core.go index 6501f48a88..4a9a5db251 100644 --- a/federation/cmd/federation-apiserver/app/core.go +++ b/federation/cmd/federation-apiserver/app/core.go @@ -30,7 +30,6 @@ import ( _ "k8s.io/kubernetes/federation/apis/core/install" "k8s.io/kubernetes/federation/apis/core/v1" "k8s.io/kubernetes/federation/cmd/federation-apiserver/app/options" - "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apimachinery/registered" "k8s.io/kubernetes/pkg/genericapiserver" @@ -39,14 +38,15 @@ import ( namespaceetcd "k8s.io/kubernetes/pkg/registry/core/namespace/etcd" secretetcd "k8s.io/kubernetes/pkg/registry/core/secret/etcd" serviceetcd "k8s.io/kubernetes/pkg/registry/core/service/etcd" + "k8s.io/kubernetes/pkg/registry/generic" ) -func installCoreAPIs(s *options.ServerRunOptions, g *genericapiserver.GenericAPIServer, restOptionsFactory restOptionsFactory) { - serviceStore, serviceStatusStore := serviceetcd.NewREST(restOptionsFactory.NewFor(api.Resource("service"))) - namespaceStore, namespaceStatusStore, namespaceFinalizeStore := namespaceetcd.NewREST(restOptionsFactory.NewFor(api.Resource("namespaces"))) - secretStore := secretetcd.NewREST(restOptionsFactory.NewFor(api.Resource("secrets"))) - configMapStore := configmapetcd.NewREST(restOptionsFactory.NewFor(api.Resource("configmaps"))) - eventStore := eventetcd.NewREST(restOptionsFactory.NewFor(api.Resource("events")), uint64(s.EventTTL.Seconds())) +func installCoreAPIs(s *options.ServerRunOptions, g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter) { + serviceStore, serviceStatusStore := serviceetcd.NewREST(optsGetter) + namespaceStore, namespaceStatusStore, namespaceFinalizeStore := namespaceetcd.NewREST(optsGetter) + secretStore := secretetcd.NewREST(optsGetter) + configMapStore := configmapetcd.NewREST(optsGetter) + eventStore := eventetcd.NewREST(optsGetter, uint64(s.EventTTL.Seconds())) coreResources := map[string]rest.Storage{ "secrets": secretStore, "services": serviceStore, diff --git a/federation/cmd/federation-apiserver/app/extensions.go b/federation/cmd/federation-apiserver/app/extensions.go index d101b38b91..896ff2447d 100644 --- a/federation/cmd/federation-apiserver/app/extensions.go +++ b/federation/cmd/federation-apiserver/app/extensions.go @@ -28,13 +28,14 @@ import ( deploymentetcd "k8s.io/kubernetes/pkg/registry/extensions/deployment/etcd" ingressetcd "k8s.io/kubernetes/pkg/registry/extensions/ingress/etcd" replicasetetcd "k8s.io/kubernetes/pkg/registry/extensions/replicaset/etcd" + "k8s.io/kubernetes/pkg/registry/generic" ) -func installExtensionsAPIs(g *genericapiserver.GenericAPIServer, restOptionsFactory restOptionsFactory) { - replicaSetStorage := replicasetetcd.NewStorage(restOptionsFactory.NewFor(extensions.Resource("replicasets"))) - deploymentStorage := deploymentetcd.NewStorage(restOptionsFactory.NewFor(extensions.Resource("deployments"))) - ingressStorage, ingressStatusStorage := ingressetcd.NewREST(restOptionsFactory.NewFor(extensions.Resource("ingresses"))) - daemonSetStorage, daemonSetStatusStorage := daemonsetetcd.NewREST(restOptionsFactory.NewFor(extensions.Resource("daemonsets"))) +func installExtensionsAPIs(g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter) { + replicaSetStorage := replicasetetcd.NewStorage(optsGetter) + deploymentStorage := deploymentetcd.NewStorage(optsGetter) + ingressStorage, ingressStatusStorage := ingressetcd.NewREST(optsGetter) + daemonSetStorage, daemonSetStatusStorage := daemonsetetcd.NewREST(optsGetter) extensionsResources := map[string]rest.Storage{ "replicasets": replicaSetStorage.ReplicaSet, diff --git a/federation/cmd/federation-apiserver/app/federation.go b/federation/cmd/federation-apiserver/app/federation.go index c113f60cbd..2856ef48e9 100644 --- a/federation/cmd/federation-apiserver/app/federation.go +++ b/federation/cmd/federation-apiserver/app/federation.go @@ -24,13 +24,14 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apimachinery/registered" "k8s.io/kubernetes/pkg/genericapiserver" + "k8s.io/kubernetes/pkg/registry/generic" _ "k8s.io/kubernetes/federation/apis/federation/install" clusteretcd "k8s.io/kubernetes/federation/registry/cluster/etcd" ) -func installFederationAPIs(g *genericapiserver.GenericAPIServer, restOptionsFactory restOptionsFactory) { - clusterStorage, clusterStatusStorage := clusteretcd.NewREST(restOptionsFactory.NewFor(federation.Resource("clusters"))) +func installFederationAPIs(g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter) { + clusterStorage, clusterStatusStorage := clusteretcd.NewREST(optsGetter) federationResources := map[string]rest.Storage{ "clusters": clusterStorage, "clusters/status": clusterStatusStorage, diff --git a/federation/cmd/federation-apiserver/app/server.go b/federation/cmd/federation-apiserver/app/server.go index 3817b0b0c0..73ca7866ce 100644 --- a/federation/cmd/federation-apiserver/app/server.go +++ b/federation/cmd/federation-apiserver/app/server.go @@ -188,7 +188,7 @@ func Run(s *options.ServerRunOptions) error { routes.Logs{}.Install(m.HandlerContainer) // TODO: Refactor this code to share it with kube-apiserver rather than duplicating it here. - restOptionsFactory := restOptionsFactory{ + restOptionsFactory := &restOptionsFactory{ storageFactory: storageFactory, enableGarbageCollection: s.GenericServerRunOptions.EnableGarbageCollection, deleteCollectionWorkers: s.GenericServerRunOptions.DeleteCollectionWorkers, @@ -215,10 +215,10 @@ type restOptionsFactory struct { enableGarbageCollection bool } -func (f restOptionsFactory) NewFor(resource schema.GroupResource) generic.RESTOptions { +func (f *restOptionsFactory) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) { config, err := f.storageFactory.NewConfig(resource) if err != nil { - glog.Fatalf("Unable to find storage config for %v, due to %v", resource, err.Error()) + return generic.RESTOptions{}, fmt.Errorf("Unable to find storage config for %v, due to %v", resource, err.Error()) } return generic.RESTOptions{ StorageConfig: config, @@ -226,5 +226,5 @@ func (f restOptionsFactory) NewFor(resource schema.GroupResource) generic.RESTOp DeleteCollectionWorkers: f.deleteCollectionWorkers, EnableGarbageCollection: f.enableGarbageCollection, ResourcePrefix: f.storageFactory.ResourcePrefix(resource), - } + }, nil } diff --git a/federation/registry/cluster/etcd/BUILD b/federation/registry/cluster/etcd/BUILD index 6381b8ed4d..25b5f23ae5 100644 --- a/federation/registry/cluster/etcd/BUILD +++ b/federation/registry/cluster/etcd/BUILD @@ -22,7 +22,6 @@ go_library( "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/federation/registry/cluster/etcd/etcd.go b/federation/registry/cluster/etcd/etcd.go index 7bbe2e3e9e..dc690305aa 100644 --- a/federation/registry/cluster/etcd/etcd.go +++ b/federation/registry/cluster/etcd/etcd.go @@ -24,7 +24,6 @@ import ( "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) type REST struct { @@ -45,45 +44,24 @@ func (r *StatusREST) Update(ctx api.Context, name string, objInfo rest.UpdatedOb } // NewREST returns a RESTStorage object that will work against clusters. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &federation.ClusterList{} } - storageInterface, _ := opts.Decorator( - opts.StorageConfig, - 100, - &federation.Cluster{}, - prefix, - cluster.Strategy, - newListFunc, - cluster.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &federation.Cluster{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return prefix - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NoNamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &federation.ClusterList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*federation.Cluster).Name, nil }, - PredicateFunc: cluster.MatchCluster, - QualifiedResource: federation.Resource("clusters"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, - - CreateStrategy: cluster.Strategy, - UpdateStrategy: cluster.Strategy, - DeleteStrategy: cluster.Strategy, + PredicateFunc: cluster.MatchCluster, + QualifiedResource: federation.Resource("clusters"), + CreateStrategy: cluster.Strategy, + UpdateStrategy: cluster.Strategy, + DeleteStrategy: cluster.Strategy, ReturnDeletedObject: true, - - Storage: storageInterface, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: cluster.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } statusStore := *store diff --git a/federation/registry/cluster/etcd/etcd_test.go b/federation/registry/cluster/etcd/etcd_test.go index b53a4db8be..acb107cfa8 100644 --- a/federation/registry/cluster/etcd/etcd_test.go +++ b/federation/registry/cluster/etcd/etcd_test.go @@ -34,7 +34,9 @@ func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { restOptions := generic.RESTOptions{ StorageConfig: storageConfig, Decorator: generic.UndecoratedStorage, - DeleteCollectionWorkers: 1} + DeleteCollectionWorkers: 1, + ResourcePrefix: "clusters", + } storage, _ := NewREST(restOptions) return storage, server } diff --git a/hack/.linted_packages b/hack/.linted_packages index e3f25cf127..af5f00446e 100644 --- a/hack/.linted_packages +++ b/hack/.linted_packages @@ -262,6 +262,7 @@ pkg/util/metrics pkg/util/netsh pkg/util/ratelimit pkg/util/replicaset +pkg/util/restoptions pkg/util/validation/field pkg/util/workqueue pkg/version/prometheus diff --git a/pkg/controller/serviceaccount/tokengetter.go b/pkg/controller/serviceaccount/tokengetter.go index 37b88f2b5a..35551bf350 100644 --- a/pkg/controller/serviceaccount/tokengetter.go +++ b/pkg/controller/serviceaccount/tokengetter.go @@ -86,8 +86,10 @@ func (r *registryGetter) GetSecret(namespace, name string) (*v1.Secret, error) { // NewGetterFromStorageInterface returns a ServiceAccountTokenGetter that // uses the specified storage to retrieve service accounts and secrets. func NewGetterFromStorageInterface(config *storagebackend.Config, saPrefix, secretPrefix string) serviceaccount.ServiceAccountTokenGetter { + saOpts := generic.RESTOptions{StorageConfig: config, Decorator: generic.UndecoratedStorage, ResourcePrefix: saPrefix} + secretOpts := generic.RESTOptions{StorageConfig: config, Decorator: generic.UndecoratedStorage, ResourcePrefix: secretPrefix} return NewGetterFromRegistries( - serviceaccountregistry.NewRegistry(serviceaccountetcd.NewREST(generic.RESTOptions{StorageConfig: config, Decorator: generic.UndecoratedStorage, ResourcePrefix: saPrefix})), - secret.NewRegistry(secretetcd.NewREST(generic.RESTOptions{StorageConfig: config, Decorator: generic.UndecoratedStorage, ResourcePrefix: secretPrefix})), + serviceaccountregistry.NewRegistry(serviceaccountetcd.NewREST(saOpts)), + secret.NewRegistry(secretetcd.NewREST(secretOpts)), ) } diff --git a/pkg/genericapiserver/storage_factory.go b/pkg/genericapiserver/storage_factory.go index f6a097e215..e2b84be45d 100644 --- a/pkg/genericapiserver/storage_factory.go +++ b/pkg/genericapiserver/storage_factory.go @@ -104,12 +104,13 @@ const AllResources = "*" // specialDefaultResourcePrefixes are prefixes compiled into Kubernetes. // TODO: move out of this package, it is not generic var specialDefaultResourcePrefixes = map[schema.GroupResource]string{ - schema.GroupResource{Group: "", Resource: "replicationControllers"}: "controllers", - schema.GroupResource{Group: "", Resource: "replicationcontrollers"}: "controllers", - schema.GroupResource{Group: "", Resource: "endpoints"}: "services/endpoints", - schema.GroupResource{Group: "", Resource: "nodes"}: "minions", - schema.GroupResource{Group: "", Resource: "services"}: "services/specs", - schema.GroupResource{Group: "extensions", Resource: "ingresses"}: "ingress", + schema.GroupResource{Group: "", Resource: "replicationControllers"}: "controllers", + schema.GroupResource{Group: "", Resource: "replicationcontrollers"}: "controllers", + schema.GroupResource{Group: "", Resource: "endpoints"}: "services/endpoints", + schema.GroupResource{Group: "", Resource: "nodes"}: "minions", + schema.GroupResource{Group: "", Resource: "services"}: "services/specs", + schema.GroupResource{Group: "extensions", Resource: "ingresses"}: "ingress", + schema.GroupResource{Group: "extensions", Resource: "podsecuritypolicies"}: "podsecuritypolicy", } func NewDefaultStorageFactory(config storagebackend.Config, defaultMediaType string, defaultSerializer runtime.StorageSerializer, resourceEncodingConfig ResourceEncodingConfig, resourceConfig APIResourceConfigSource) *DefaultStorageFactory { diff --git a/pkg/master/BUILD b/pkg/master/BUILD index 03941208ad..046cf5af88 100644 --- a/pkg/master/BUILD +++ b/pkg/master/BUILD @@ -56,7 +56,6 @@ go_library( "//pkg/healthz:go_default_library", "//pkg/kubelet/client:go_default_library", "//pkg/master/thirdparty:go_default_library", - "//pkg/registry:go_default_library", "//pkg/registry/apps/rest:go_default_library", "//pkg/registry/authentication/rest:go_default_library", "//pkg/registry/authorization/rest:go_default_library", diff --git a/pkg/master/master.go b/pkg/master/master.go index 357592daa7..7a4b6d4056 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -43,7 +43,6 @@ import ( "k8s.io/kubernetes/pkg/healthz" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/master/thirdparty" - "k8s.io/kubernetes/pkg/registry" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/routes" @@ -219,7 +218,7 @@ func (c completedConfig) New() (*Master, error) { GenericAPIServer: s, } - restOptionsFactory := restOptionsFactory{ + restOptionsFactory := &restOptionsFactory{ deleteCollectionWorkers: c.DeleteCollectionWorkers, enableGarbageCollection: c.GenericConfig.EnableGarbageCollection, storageFactory: c.StorageFactory, @@ -242,7 +241,7 @@ func (c completedConfig) New() (*Master, error) { ServiceNodePortRange: c.ServiceNodePortRange, LoopbackClientConfig: c.GenericConfig.LoopbackClientConfig, } - m.InstallLegacyAPI(c.Config, restOptionsFactory.NewFor, legacyRESTStorageProvider) + m.InstallLegacyAPI(c.Config, restOptionsFactory, legacyRESTStorageProvider) } restStorageProviders := []RESTStorageProvider{ @@ -257,7 +256,7 @@ func (c completedConfig) New() (*Master, error) { rbacrest.RESTStorageProvider{}, storagerest.RESTStorageProvider{}, } - m.InstallAPIs(c.Config.APIResourceConfigSource, restOptionsFactory.NewFor, restStorageProviders...) + m.InstallAPIs(c.Config.APIResourceConfigSource, restOptionsFactory, restStorageProviders...) if c.Tunneler != nil { m.installTunneler(c.Tunneler, corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig).Nodes()) @@ -266,7 +265,7 @@ func (c completedConfig) New() (*Master, error) { return m, nil } -func (m *Master) InstallLegacyAPI(c *Config, restOptionsGetter registry.RESTOptionsGetter, legacyRESTStorageProvider corerest.LegacyRESTStorageProvider) { +func (m *Master) InstallLegacyAPI(c *Config, restOptionsGetter generic.RESTOptionsGetter, legacyRESTStorageProvider corerest.LegacyRESTStorageProvider) { legacyRESTStorage, apiGroupInfo, err := legacyRESTStorageProvider.NewLegacyRESTStorage(restOptionsGetter) if err != nil { glog.Fatalf("Error building core storage: %v", err) @@ -297,11 +296,11 @@ func (m *Master) installTunneler(tunneler genericapiserver.Tunneler, nodeClient // RESTStorageProvider is a factory type for REST storage. type RESTStorageProvider interface { GroupName() string - NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) + NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) } // InstallAPIs will install the APIs for the restStorageProviders if they are enabled. -func (m *Master) InstallAPIs(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter, restStorageProviders ...RESTStorageProvider) { +func (m *Master) InstallAPIs(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter, restStorageProviders ...RESTStorageProvider) { apiGroupsInfo := []genericapiserver.APIGroupInfo{} for _, restStorageBuilder := range restStorageProviders { @@ -344,10 +343,10 @@ type restOptionsFactory struct { storageDecorator generic.StorageDecorator } -func (f restOptionsFactory) NewFor(resource schema.GroupResource) generic.RESTOptions { +func (f *restOptionsFactory) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) { storageConfig, err := f.storageFactory.NewConfig(resource) if err != nil { - glog.Fatalf("Unable to find storage destination for %v, due to %v", resource, err.Error()) + return generic.RESTOptions{}, fmt.Errorf("Unable to find storage destination for %v, due to %v", resource, err.Error()) } return generic.RESTOptions{ @@ -356,7 +355,7 @@ func (f restOptionsFactory) NewFor(resource schema.GroupResource) generic.RESTOp DeleteCollectionWorkers: f.deleteCollectionWorkers, EnableGarbageCollection: f.enableGarbageCollection, ResourcePrefix: f.storageFactory.ResourcePrefix(resource), - } + }, nil } type nodeAddressProvider struct { diff --git a/pkg/registry/BUILD b/pkg/registry/BUILD index 28368ab522..b80bb3379f 100644 --- a/pkg/registry/BUILD +++ b/pkg/registry/BUILD @@ -12,13 +12,6 @@ load( go_library( name = "go_default_library", - srcs = [ - "doc.go", - "interfaces.go", - ], + srcs = ["doc.go"], tags = ["automanaged"], - deps = [ - "//pkg/registry/generic:go_default_library", - "//pkg/runtime/schema:go_default_library", - ], ) diff --git a/pkg/registry/apps/petset/etcd/BUILD b/pkg/registry/apps/petset/etcd/BUILD index 54df862b43..e3921ff6d9 100644 --- a/pkg/registry/apps/petset/etcd/BUILD +++ b/pkg/registry/apps/petset/etcd/BUILD @@ -20,11 +20,9 @@ go_library( "//pkg/apis/apps:go_default_library", "//pkg/apis/meta/v1:go_default_library", "//pkg/registry/apps/petset:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/apps/petset/etcd/etcd.go b/pkg/registry/apps/petset/etcd/etcd.go index 667863dcc7..dcaab06b35 100644 --- a/pkg/registry/apps/petset/etcd/etcd.go +++ b/pkg/registry/apps/petset/etcd/etcd.go @@ -22,11 +22,9 @@ import ( appsapi "k8s.io/kubernetes/pkg/apis/apps" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/registry/apps/petset" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // rest implements a RESTStorage for replication controllers against etcd @@ -35,56 +33,25 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against replication controllers. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &appsapi.StatefulSetList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.StatefulSet), - &appsapi.StatefulSet{}, - prefix, - petset.Strategy, - newListFunc, - petset.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &appsapi.StatefulSet{} }, - - // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a statefulSet that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - // Produces a statefulSet that etcd understands, to the resource by combining - // the namespace in the context with the given prefix - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, - // Retrieve the name field of a replication controller + NewFunc: func() runtime.Object { return &appsapi.StatefulSet{} }, + NewListFunc: func() runtime.Object { return &appsapi.StatefulSetList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*appsapi.StatefulSet).Name, nil }, - // Used to match objects based on labels/fields for list and watch - PredicateFunc: petset.MatchStatefulSet, - QualifiedResource: appsapi.Resource("statefulsets"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: petset.MatchStatefulSet, + QualifiedResource: appsapi.Resource("statefulsets"), - // Used to validate controller creation CreateStrategy: petset.Strategy, - - // Used to validate controller updates UpdateStrategy: petset.Strategy, DeleteStrategy: petset.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: petset.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up + } + statusStore := *store statusStore.UpdateStrategy = petset.StatusStrategy return &REST{store}, &StatusREST{store: &statusStore} diff --git a/pkg/registry/apps/rest/BUILD b/pkg/registry/apps/rest/BUILD index 720aa2d27e..05dd24cae8 100644 --- a/pkg/registry/apps/rest/BUILD +++ b/pkg/registry/apps/rest/BUILD @@ -19,7 +19,7 @@ go_library( "//pkg/apis/apps:go_default_library", "//pkg/apis/apps/v1beta1:go_default_library", "//pkg/genericapiserver:go_default_library", - "//pkg/registry:go_default_library", "//pkg/registry/apps/petset/etcd:go_default_library", + "//pkg/registry/generic:go_default_library", ], ) diff --git a/pkg/registry/apps/rest/storage_apps.go b/pkg/registry/apps/rest/storage_apps.go index 057251a602..3827e43f7f 100644 --- a/pkg/registry/apps/rest/storage_apps.go +++ b/pkg/registry/apps/rest/storage_apps.go @@ -21,13 +21,13 @@ import ( "k8s.io/kubernetes/pkg/apis/apps" appsapiv1beta1 "k8s.io/kubernetes/pkg/apis/apps/v1beta1" "k8s.io/kubernetes/pkg/genericapiserver" - "k8s.io/kubernetes/pkg/registry" statefulsetetcd "k8s.io/kubernetes/pkg/registry/apps/petset/etcd" + "k8s.io/kubernetes/pkg/registry/generic" ) type RESTStorageProvider struct{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apps.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(appsapiv1beta1.SchemeGroupVersion) { @@ -38,12 +38,12 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapise return apiGroupInfo, true } -func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { version := appsapiv1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} if apiResourceConfigSource.ResourceEnabled(version.WithResource("statefulsets")) { - statefulsetStorage, statefulsetStatusStorage := statefulsetetcd.NewREST(restOptionsGetter(apps.Resource("statefulsets"))) + statefulsetStorage, statefulsetStatusStorage := statefulsetetcd.NewREST(restOptionsGetter) storage["statefulsets"] = statefulsetStorage storage["statefulsets/status"] = statefulsetStatusStorage } diff --git a/pkg/registry/authentication/rest/BUILD b/pkg/registry/authentication/rest/BUILD index 0e91c7f651..24054bfb6a 100644 --- a/pkg/registry/authentication/rest/BUILD +++ b/pkg/registry/authentication/rest/BUILD @@ -20,7 +20,7 @@ go_library( "//pkg/apis/authentication/v1beta1:go_default_library", "//pkg/auth/authenticator:go_default_library", "//pkg/genericapiserver:go_default_library", - "//pkg/registry:go_default_library", "//pkg/registry/authentication/tokenreview:go_default_library", + "//pkg/registry/generic:go_default_library", ], ) diff --git a/pkg/registry/authentication/rest/storage_authentication.go b/pkg/registry/authentication/rest/storage_authentication.go index 1ee8b4f9b2..397072d938 100644 --- a/pkg/registry/authentication/rest/storage_authentication.go +++ b/pkg/registry/authentication/rest/storage_authentication.go @@ -22,15 +22,15 @@ import ( authenticationv1beta1 "k8s.io/kubernetes/pkg/apis/authentication/v1beta1" "k8s.io/kubernetes/pkg/auth/authenticator" "k8s.io/kubernetes/pkg/genericapiserver" - "k8s.io/kubernetes/pkg/registry" "k8s.io/kubernetes/pkg/registry/authentication/tokenreview" + "k8s.io/kubernetes/pkg/registry/generic" ) type RESTStorageProvider struct { Authenticator authenticator.Request } -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { // TODO figure out how to make the swagger generation stable, while allowing this endpoint to be disabled. // if p.Authenticator == nil { // return genericapiserver.APIGroupInfo{}, false @@ -46,7 +46,7 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapise return apiGroupInfo, true } -func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { version := authenticationv1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} diff --git a/pkg/registry/authorization/rest/BUILD b/pkg/registry/authorization/rest/BUILD index 7dee0237cb..b556107770 100644 --- a/pkg/registry/authorization/rest/BUILD +++ b/pkg/registry/authorization/rest/BUILD @@ -20,9 +20,9 @@ go_library( "//pkg/apis/authorization/v1beta1:go_default_library", "//pkg/auth/authorizer:go_default_library", "//pkg/genericapiserver:go_default_library", - "//pkg/registry:go_default_library", "//pkg/registry/authorization/localsubjectaccessreview:go_default_library", "//pkg/registry/authorization/selfsubjectaccessreview:go_default_library", "//pkg/registry/authorization/subjectaccessreview:go_default_library", + "//pkg/registry/generic:go_default_library", ], ) diff --git a/pkg/registry/authorization/rest/storage_authorization.go b/pkg/registry/authorization/rest/storage_authorization.go index b4e951e8d8..6c975fc358 100644 --- a/pkg/registry/authorization/rest/storage_authorization.go +++ b/pkg/registry/authorization/rest/storage_authorization.go @@ -22,17 +22,17 @@ import ( authorizationv1beta1 "k8s.io/kubernetes/pkg/apis/authorization/v1beta1" "k8s.io/kubernetes/pkg/auth/authorizer" "k8s.io/kubernetes/pkg/genericapiserver" - "k8s.io/kubernetes/pkg/registry" "k8s.io/kubernetes/pkg/registry/authorization/localsubjectaccessreview" "k8s.io/kubernetes/pkg/registry/authorization/selfsubjectaccessreview" "k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview" + "k8s.io/kubernetes/pkg/registry/generic" ) type RESTStorageProvider struct { Authorizer authorizer.Authorizer } -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { if p.Authorizer == nil { return genericapiserver.APIGroupInfo{}, false } @@ -47,7 +47,7 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapise return apiGroupInfo, true } -func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { version := authorizationv1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} diff --git a/pkg/registry/autoscaling/horizontalpodautoscaler/etcd/BUILD b/pkg/registry/autoscaling/horizontalpodautoscaler/etcd/BUILD index 453e0e3b69..0b0d58f2f8 100644 --- a/pkg/registry/autoscaling/horizontalpodautoscaler/etcd/BUILD +++ b/pkg/registry/autoscaling/horizontalpodautoscaler/etcd/BUILD @@ -20,11 +20,9 @@ go_library( "//pkg/apis/autoscaling:go_default_library", "//pkg/apis/meta/v1:go_default_library", "//pkg/registry/autoscaling/horizontalpodautoscaler:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/autoscaling/horizontalpodautoscaler/etcd/etcd.go b/pkg/registry/autoscaling/horizontalpodautoscaler/etcd/etcd.go index de5d34e018..de8c0fc3d6 100644 --- a/pkg/registry/autoscaling/horizontalpodautoscaler/etcd/etcd.go +++ b/pkg/registry/autoscaling/horizontalpodautoscaler/etcd/etcd.go @@ -22,11 +22,9 @@ import ( "k8s.io/kubernetes/pkg/apis/autoscaling" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) type REST struct { @@ -34,55 +32,25 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against horizontal pod autoscalers. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &autoscaling.HorizontalPodAutoscalerList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.HorizontalPodAutoscalers), - &autoscaling.HorizontalPodAutoscaler{}, - prefix, - horizontalpodautoscaler.Strategy, - newListFunc, - horizontalpodautoscaler.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscaler{} }, - // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a path that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - // Produces a path that etcd understands, to the resource by combining - // the namespace in the context with the given prefix - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, - // Retrieve the name field of an autoscaler + NewFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscaler{} }, + NewListFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscalerList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*autoscaling.HorizontalPodAutoscaler).Name, nil }, - // Used to match objects based on labels/fields for list - PredicateFunc: horizontalpodautoscaler.MatchAutoscaler, - QualifiedResource: autoscaling.Resource("horizontalpodautoscalers"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: horizontalpodautoscaler.MatchAutoscaler, + QualifiedResource: autoscaling.Resource("horizontalpodautoscalers"), - // Used to validate autoscaler creation CreateStrategy: horizontalpodautoscaler.Strategy, - - // Used to validate autoscaler updates UpdateStrategy: horizontalpodautoscaler.Strategy, DeleteStrategy: horizontalpodautoscaler.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: horizontalpodautoscaler.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up + } + statusStore := *store statusStore.UpdateStrategy = horizontalpodautoscaler.StatusStrategy return &REST{store}, &StatusREST{store: &statusStore} diff --git a/pkg/registry/autoscaling/horizontalpodautoscaler/etcd/etcd_test.go b/pkg/registry/autoscaling/horizontalpodautoscaler/etcd/etcd_test.go index a474d75350..2db80d7ab7 100644 --- a/pkg/registry/autoscaling/horizontalpodautoscaler/etcd/etcd_test.go +++ b/pkg/registry/autoscaling/horizontalpodautoscaler/etcd/etcd_test.go @@ -33,7 +33,12 @@ import ( func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, autoscaling.GroupName) - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "horizontalpodautoscalers", + } horizontalPodAutoscalerStorage, statusStorage := NewREST(restOptions) return horizontalPodAutoscalerStorage, statusStorage, server } diff --git a/pkg/registry/autoscaling/rest/BUILD b/pkg/registry/autoscaling/rest/BUILD index 320e7ace3d..a765397a90 100644 --- a/pkg/registry/autoscaling/rest/BUILD +++ b/pkg/registry/autoscaling/rest/BUILD @@ -19,7 +19,7 @@ go_library( "//pkg/apis/autoscaling:go_default_library", "//pkg/apis/autoscaling/v1:go_default_library", "//pkg/genericapiserver:go_default_library", - "//pkg/registry:go_default_library", "//pkg/registry/autoscaling/horizontalpodautoscaler/etcd:go_default_library", + "//pkg/registry/generic:go_default_library", ], ) diff --git a/pkg/registry/autoscaling/rest/storage_autoscaling.go b/pkg/registry/autoscaling/rest/storage_autoscaling.go index 7fcf035e8c..95dd32f4e3 100644 --- a/pkg/registry/autoscaling/rest/storage_autoscaling.go +++ b/pkg/registry/autoscaling/rest/storage_autoscaling.go @@ -21,13 +21,13 @@ import ( "k8s.io/kubernetes/pkg/apis/autoscaling" autoscalingapiv1 "k8s.io/kubernetes/pkg/apis/autoscaling/v1" "k8s.io/kubernetes/pkg/genericapiserver" - "k8s.io/kubernetes/pkg/registry" horizontalpodautoscaleretcd "k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/etcd" + "k8s.io/kubernetes/pkg/registry/generic" ) type RESTStorageProvider struct{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(autoscaling.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(autoscalingapiv1.SchemeGroupVersion) { @@ -38,12 +38,12 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapise return apiGroupInfo, true } -func (p RESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { version := autoscalingapiv1.SchemeGroupVersion storage := map[string]rest.Storage{} if apiResourceConfigSource.ResourceEnabled(version.WithResource("horizontalpodautoscalers")) { - hpaStorage, hpaStatusStorage := horizontalpodautoscaleretcd.NewREST(restOptionsGetter(autoscaling.Resource("horizontalpodautoscalers"))) + hpaStorage, hpaStatusStorage := horizontalpodautoscaleretcd.NewREST(restOptionsGetter) storage["horizontalpodautoscalers"] = hpaStorage storage["horizontalpodautoscalers/status"] = hpaStatusStorage } diff --git a/pkg/registry/batch/cronjob/etcd/BUILD b/pkg/registry/batch/cronjob/etcd/BUILD index 39555fe3ec..679c15fa60 100644 --- a/pkg/registry/batch/cronjob/etcd/BUILD +++ b/pkg/registry/batch/cronjob/etcd/BUILD @@ -20,11 +20,9 @@ go_library( "//pkg/apis/batch:go_default_library", "//pkg/apis/meta/v1:go_default_library", "//pkg/registry/batch/cronjob:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/batch/cronjob/etcd/etcd.go b/pkg/registry/batch/cronjob/etcd/etcd.go index 35cf8764ab..63820e6546 100644 --- a/pkg/registry/batch/cronjob/etcd/etcd.go +++ b/pkg/registry/batch/cronjob/etcd/etcd.go @@ -22,11 +22,9 @@ import ( "k8s.io/kubernetes/pkg/apis/batch" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/registry/batch/cronjob" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // REST implements a RESTStorage for scheduled jobs against etcd @@ -35,55 +33,23 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against CronJobs. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &batch.CronJobList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.CronJobs), - &batch.CronJob{}, - prefix, - cronjob.Strategy, - newListFunc, - cronjob.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &batch.CronJob{} }, - - // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a path that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - // Produces a path that etcd understands, to the resource by combining - // the namespace in the context with the given prefix - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, - // Retrieve the name field of a scheduled job + NewFunc: func() runtime.Object { return &batch.CronJob{} }, + NewListFunc: func() runtime.Object { return &batch.CronJobList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*batch.CronJob).Name, nil }, - // Used to match objects based on labels/fields for list and watch - PredicateFunc: cronjob.MatchCronJob, - QualifiedResource: batch.Resource("cronjobs"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: cronjob.MatchCronJob, + QualifiedResource: batch.Resource("cronjobs"), - // Used to validate scheduled job creation CreateStrategy: cronjob.Strategy, - - // Used to validate scheduled job updates UpdateStrategy: cronjob.Strategy, DeleteStrategy: cronjob.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: cronjob.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } statusStore := *store diff --git a/pkg/registry/batch/job/etcd/BUILD b/pkg/registry/batch/job/etcd/BUILD index ec20241954..ae841868f1 100644 --- a/pkg/registry/batch/job/etcd/BUILD +++ b/pkg/registry/batch/job/etcd/BUILD @@ -20,11 +20,9 @@ go_library( "//pkg/apis/batch:go_default_library", "//pkg/apis/meta/v1:go_default_library", "//pkg/registry/batch/job:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/batch/job/etcd/etcd.go b/pkg/registry/batch/job/etcd/etcd.go index 20a49e83c9..7e77e13fca 100644 --- a/pkg/registry/batch/job/etcd/etcd.go +++ b/pkg/registry/batch/job/etcd/etcd.go @@ -22,11 +22,9 @@ import ( "k8s.io/kubernetes/pkg/apis/batch" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/registry/batch/job" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // REST implements a RESTStorage for jobs against etcd @@ -35,55 +33,23 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against Jobs. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &batch.JobList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Jobs), - &batch.Job{}, - prefix, - job.Strategy, - newListFunc, - job.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &batch.Job{} }, - - // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a path that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - // Produces a path that etcd understands, to the resource by combining - // the namespace in the context with the given prefix - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, - // Retrieve the name field of a job + NewFunc: func() runtime.Object { return &batch.Job{} }, + NewListFunc: func() runtime.Object { return &batch.JobList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*batch.Job).Name, nil }, - // Used to match objects based on labels/fields for list and watch - PredicateFunc: job.MatchJob, - QualifiedResource: batch.Resource("jobs"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: job.MatchJob, + QualifiedResource: batch.Resource("jobs"), - // Used to validate job creation CreateStrategy: job.Strategy, - - // Used to validate job updates UpdateStrategy: job.Strategy, DeleteStrategy: job.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: job.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } statusStore := *store diff --git a/pkg/registry/batch/job/etcd/etcd_test.go b/pkg/registry/batch/job/etcd/etcd_test.go index 0835551a4c..58b459e16f 100644 --- a/pkg/registry/batch/job/etcd/etcd_test.go +++ b/pkg/registry/batch/job/etcd/etcd_test.go @@ -33,7 +33,12 @@ import ( func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, extensions.GroupName) - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "jobs", + } jobStorage, statusStorage := NewREST(restOptions) return jobStorage, statusStorage, server } diff --git a/pkg/registry/batch/rest/BUILD b/pkg/registry/batch/rest/BUILD index a5983a079e..6dd508c8b7 100644 --- a/pkg/registry/batch/rest/BUILD +++ b/pkg/registry/batch/rest/BUILD @@ -20,9 +20,9 @@ go_library( "//pkg/apis/batch/v1:go_default_library", "//pkg/apis/batch/v2alpha1:go_default_library", "//pkg/genericapiserver:go_default_library", - "//pkg/registry:go_default_library", "//pkg/registry/batch/cronjob/etcd:go_default_library", "//pkg/registry/batch/job/etcd:go_default_library", + "//pkg/registry/generic:go_default_library", "//pkg/runtime/schema:go_default_library", ], ) diff --git a/pkg/registry/batch/rest/storage_batch.go b/pkg/registry/batch/rest/storage_batch.go index 9d0f15b33c..3b353bae58 100644 --- a/pkg/registry/batch/rest/storage_batch.go +++ b/pkg/registry/batch/rest/storage_batch.go @@ -22,15 +22,15 @@ import ( batchapiv1 "k8s.io/kubernetes/pkg/apis/batch/v1" batchapiv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1" "k8s.io/kubernetes/pkg/genericapiserver" - "k8s.io/kubernetes/pkg/registry" cronjobetcd "k8s.io/kubernetes/pkg/registry/batch/cronjob/etcd" jobetcd "k8s.io/kubernetes/pkg/registry/batch/job/etcd" + "k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/runtime/schema" ) type RESTStorageProvider struct{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(batch.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv2alpha1.SchemeGroupVersion) { @@ -49,29 +49,29 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapise return apiGroupInfo, true } -func (p RESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { version := batchapiv1.SchemeGroupVersion storage := map[string]rest.Storage{} if apiResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) { - jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter(batch.Resource("jobs"))) + jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter) storage["jobs"] = jobsStorage storage["jobs/status"] = jobsStatusStorage } return storage } -func (p RESTStorageProvider) v2alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v2alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { version := batchapiv2alpha1.SchemeGroupVersion storage := map[string]rest.Storage{} if apiResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) { - jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter(batch.Resource("jobs"))) + jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter) storage["jobs"] = jobsStorage storage["jobs/status"] = jobsStatusStorage } if apiResourceConfigSource.ResourceEnabled(version.WithResource("cronjobs")) { - cronJobsStorage, cronJobsStatusStorage := cronjobetcd.NewREST(restOptionsGetter(batch.Resource("cronjobs"))) + cronJobsStorage, cronJobsStatusStorage := cronjobetcd.NewREST(restOptionsGetter) storage["cronjobs"] = cronJobsStorage storage["cronjobs/status"] = cronJobsStatusStorage storage["scheduledjobs"] = cronJobsStorage diff --git a/pkg/registry/cachesize/cachesize.go b/pkg/registry/cachesize/cachesize.go index ecab39615d..1b0ae583b1 100644 --- a/pkg/registry/cachesize/cachesize.go +++ b/pkg/registry/cachesize/cachesize.go @@ -28,6 +28,7 @@ import ( type Resource string const ( + APIServices Resource = "apiservices" CertificateSigningRequests Resource = "certificatesigningrequests" ClusterRoles Resource = "clusterroles" ClusterRoleBindings Resource = "clusterrolebindings" @@ -90,6 +91,7 @@ func InitializeWatchCacheSizes(expectedRAMCapacityMB int) { watchCacheSizes[Nodes] = maxInt(5*clusterSize, 1000) watchCacheSizes[Pods] = maxInt(50*clusterSize, 1000) watchCacheSizes[Services] = maxInt(5*clusterSize, 1000) + watchCacheSizes[APIServices] = maxInt(5*clusterSize, 1000) } func SetWatchCacheSizes(cacheSizes []string) { @@ -110,7 +112,7 @@ func SetWatchCacheSizes(cacheSizes []string) { } } -func GetWatchCacheSizeByResource(resource Resource) int { +func GetWatchCacheSizeByResource(resource Resource) int { // TODO this should use schema.GroupResource for lookups if value, found := watchCacheSizes[resource]; found { return value } diff --git a/pkg/registry/certificates/certificates/etcd/BUILD b/pkg/registry/certificates/certificates/etcd/BUILD index 2389476800..b52ae8802f 100644 --- a/pkg/registry/certificates/certificates/etcd/BUILD +++ b/pkg/registry/certificates/certificates/etcd/BUILD @@ -18,13 +18,9 @@ go_library( "//pkg/api:go_default_library", "//pkg/api/rest:go_default_library", "//pkg/apis/certificates:go_default_library", - "//pkg/fields:go_default_library", - "//pkg/labels:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/certificates/certificates:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/certificates/certificates/etcd/etcd.go b/pkg/registry/certificates/certificates/etcd/etcd.go index 4c84d02b35..947909bf15 100644 --- a/pkg/registry/certificates/certificates/etcd/etcd.go +++ b/pkg/registry/certificates/certificates/etcd/etcd.go @@ -20,14 +20,10 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apis/certificates" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/registry/cachesize" csrregistry "k8s.io/kubernetes/pkg/registry/certificates/certificates" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // REST implements a RESTStorage for CertificateSigningRequest against etcd @@ -36,46 +32,23 @@ type REST struct { } // NewREST returns a registry which will store CertificateSigningRequest in the given helper -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST, *ApprovalREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &certificates.CertificateSigningRequestList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.CertificateSigningRequests), - &certificates.CertificateSigningRequest{}, - prefix, - csrregistry.Strategy, - newListFunc, - csrregistry.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *ApprovalREST) { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &certificates.CertificateSigningRequest{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return prefix - }, - KeyFunc: func(ctx api.Context, id string) (string, error) { - return genericregistry.NoNamespaceKeyFunc(ctx, prefix, id) - }, + NewListFunc: func() runtime.Object { return &certificates.CertificateSigningRequestList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*certificates.CertificateSigningRequest).Name, nil }, - PredicateFunc: func(label labels.Selector, field fields.Selector) storage.SelectionPredicate { - return csrregistry.Matcher(label, field) - }, - QualifiedResource: certificates.Resource("certificatesigningrequests"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: csrregistry.Matcher, + QualifiedResource: certificates.Resource("certificatesigningrequests"), CreateStrategy: csrregistry.Strategy, UpdateStrategy: csrregistry.Strategy, DeleteStrategy: csrregistry.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: csrregistry.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } // Subresources use the same store and creation strategy, which only diff --git a/pkg/registry/certificates/rest/BUILD b/pkg/registry/certificates/rest/BUILD index a6eefa57ad..56c6523235 100644 --- a/pkg/registry/certificates/rest/BUILD +++ b/pkg/registry/certificates/rest/BUILD @@ -19,7 +19,7 @@ go_library( "//pkg/apis/certificates:go_default_library", "//pkg/apis/certificates/v1alpha1:go_default_library", "//pkg/genericapiserver:go_default_library", - "//pkg/registry:go_default_library", "//pkg/registry/certificates/certificates/etcd:go_default_library", + "//pkg/registry/generic:go_default_library", ], ) diff --git a/pkg/registry/certificates/rest/storage_certificates.go b/pkg/registry/certificates/rest/storage_certificates.go index ba7c408b4a..5fe72fcbbc 100644 --- a/pkg/registry/certificates/rest/storage_certificates.go +++ b/pkg/registry/certificates/rest/storage_certificates.go @@ -21,13 +21,13 @@ import ( "k8s.io/kubernetes/pkg/apis/certificates" certificatesapiv1alpha1 "k8s.io/kubernetes/pkg/apis/certificates/v1alpha1" "k8s.io/kubernetes/pkg/genericapiserver" - "k8s.io/kubernetes/pkg/registry" certificateetcd "k8s.io/kubernetes/pkg/registry/certificates/certificates/etcd" + "k8s.io/kubernetes/pkg/registry/generic" ) type RESTStorageProvider struct{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(certificates.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(certificatesapiv1alpha1.SchemeGroupVersion) { @@ -38,12 +38,12 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapise return apiGroupInfo, true } -func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { version := certificatesapiv1alpha1.SchemeGroupVersion storage := map[string]rest.Storage{} if apiResourceConfigSource.ResourceEnabled(version.WithResource("certificatesigningrequests")) { - csrStorage, csrStatusStorage, csrApprovalStorage := certificateetcd.NewREST(restOptionsGetter(certificates.Resource("certificatesigningrequests"))) + csrStorage, csrStatusStorage, csrApprovalStorage := certificateetcd.NewREST(restOptionsGetter) storage["certificatesigningrequests"] = csrStorage storage["certificatesigningrequests/status"] = csrStatusStorage storage["certificatesigningrequests/approval"] = csrApprovalStorage diff --git a/pkg/registry/core/configmap/etcd/BUILD b/pkg/registry/core/configmap/etcd/BUILD index 06fbfc28a9..22de6046ee 100644 --- a/pkg/registry/core/configmap/etcd/BUILD +++ b/pkg/registry/core/configmap/etcd/BUILD @@ -16,12 +16,10 @@ go_library( tags = ["automanaged"], deps = [ "//pkg/api:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/configmap:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/core/configmap/etcd/etcd.go b/pkg/registry/core/configmap/etcd/etcd.go index 329bb6fcac..1b60e52ab8 100644 --- a/pkg/registry/core/configmap/etcd/etcd.go +++ b/pkg/registry/core/configmap/etcd/etcd.go @@ -18,12 +18,10 @@ package etcd import ( "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/configmap" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // REST implements a RESTStorage for ConfigMap against etcd @@ -32,59 +30,23 @@ type REST struct { } // NewREST returns a RESTStorage object that will work with ConfigMap objects. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.ConfigMapList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.ConfigMaps), - &api.ConfigMap{}, - prefix, - configmap.Strategy, - newListFunc, - configmap.GetAttrs, - storage.NoTriggerPublisher) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { - return &api.ConfigMap{} - }, - - // NewListFunc returns an object to store results of an etcd list. - NewListFunc: newListFunc, - - // Produces a path that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix. - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - - // Produces a path that etcd understands, to the resource by combining - // the namespace in the context with the given prefix - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, - - // Retrieves the name field of a ConfigMap object. + NewFunc: func() runtime.Object { return &api.ConfigMap{} }, + NewListFunc: func() runtime.Object { return &api.ConfigMapList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.ConfigMap).Name, nil }, - - // Matches objects based on labels/fields for list and watch - PredicateFunc: configmap.MatchConfigMap, - + PredicateFunc: configmap.MatchConfigMap, QualifiedResource: api.Resource("configmaps"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, - CreateStrategy: configmap.Strategy, UpdateStrategy: configmap.Strategy, DeleteStrategy: configmap.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: configmap.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} } diff --git a/pkg/registry/core/configmap/etcd/etcd_test.go b/pkg/registry/core/configmap/etcd/etcd_test.go index 4cd6a8090b..9b2b110513 100644 --- a/pkg/registry/core/configmap/etcd/etcd_test.go +++ b/pkg/registry/core/configmap/etcd/etcd_test.go @@ -30,7 +30,12 @@ import ( func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "configmaps", + } return NewREST(restOptions), server } diff --git a/pkg/registry/core/controller/etcd/BUILD b/pkg/registry/core/controller/etcd/BUILD index 60ecbf2420..e34a4b2ac6 100644 --- a/pkg/registry/core/controller/etcd/BUILD +++ b/pkg/registry/core/controller/etcd/BUILD @@ -22,12 +22,10 @@ go_library( "//pkg/apis/autoscaling/validation:go_default_library", "//pkg/apis/meta/v1:go_default_library", "//pkg/labels:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/controller:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/core/controller/etcd/etcd.go b/pkg/registry/core/controller/etcd/etcd.go index d127c256b1..22579cad68 100644 --- a/pkg/registry/core/controller/etcd/etcd.go +++ b/pkg/registry/core/controller/etcd/etcd.go @@ -28,12 +28,10 @@ import ( "k8s.io/kubernetes/pkg/apis/autoscaling/validation" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/controller" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // ControllerStorage includes dummy storage for Replication Controllers and for Scale subresource. @@ -43,8 +41,8 @@ type ControllerStorage struct { Scale *ScaleREST } -func NewStorage(opts generic.RESTOptions) ControllerStorage { - controllerREST, statusREST := NewREST(opts) +func NewStorage(optsGetter generic.RESTOptionsGetter) ControllerStorage { + controllerREST, statusREST := NewREST(optsGetter) controllerRegistry := controller.NewRegistry(controllerREST) return ControllerStorage{ @@ -59,57 +57,25 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against replication controllers. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.ReplicationControllerList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Controllers), - &api.ReplicationController{}, - prefix, - controller.Strategy, - newListFunc, - controller.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &api.ReplicationController{} }, - - // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a path that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - // Produces a path that etcd understands, to the resource by combining - // the namespace in the context with the given prefix - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, - // Retrieve the name field of a replication controller + NewFunc: func() runtime.Object { return &api.ReplicationController{} }, + NewListFunc: func() runtime.Object { return &api.ReplicationControllerList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.ReplicationController).Name, nil }, - // Used to match objects based on labels/fields for list and watch PredicateFunc: controller.MatchController, QualifiedResource: api.Resource("replicationcontrollers"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, - - // Used to validate controller creation CreateStrategy: controller.Strategy, - - // Used to validate controller updates UpdateStrategy: controller.Strategy, DeleteStrategy: controller.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: controller.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up + } + statusStore := *store statusStore.UpdateStrategy = controller.StatusStrategy diff --git a/pkg/registry/core/controller/etcd/etcd_test.go b/pkg/registry/core/controller/etcd/etcd_test.go index d11988f30d..10c14b9819 100644 --- a/pkg/registry/core/controller/etcd/etcd_test.go +++ b/pkg/registry/core/controller/etcd/etcd_test.go @@ -40,7 +40,12 @@ const ( func newStorage(t *testing.T) (ControllerStorage, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "replicationcontrollers", + } storage := NewStorage(restOptions) return storage, server } diff --git a/pkg/registry/core/endpoint/etcd/BUILD b/pkg/registry/core/endpoint/etcd/BUILD index 2f15328506..3d28d5e2ea 100644 --- a/pkg/registry/core/endpoint/etcd/BUILD +++ b/pkg/registry/core/endpoint/etcd/BUILD @@ -16,12 +16,10 @@ go_library( tags = ["automanaged"], deps = [ "//pkg/api:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/endpoint:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/core/endpoint/etcd/etcd.go b/pkg/registry/core/endpoint/etcd/etcd.go index 494e5fc433..2d31c8feb7 100644 --- a/pkg/registry/core/endpoint/etcd/etcd.go +++ b/pkg/registry/core/endpoint/etcd/etcd.go @@ -18,12 +18,10 @@ package etcd import ( "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/endpoint" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) type REST struct { @@ -31,44 +29,23 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against endpoints. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.EndpointsList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Endpoints), - &api.Endpoints{}, - prefix, - endpoint.Strategy, - newListFunc, - endpoint.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.Endpoints{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &api.EndpointsList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Endpoints).Name, nil }, - PredicateFunc: endpoint.MatchEndpoints, - QualifiedResource: api.Resource("endpoints"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: endpoint.MatchEndpoints, + QualifiedResource: api.Resource("endpoints"), CreateStrategy: endpoint.Strategy, UpdateStrategy: endpoint.Strategy, DeleteStrategy: endpoint.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: endpoint.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} } diff --git a/pkg/registry/core/endpoint/etcd/etcd_test.go b/pkg/registry/core/endpoint/etcd/etcd_test.go index 4692c9b9c6..6ba1a1c837 100644 --- a/pkg/registry/core/endpoint/etcd/etcd_test.go +++ b/pkg/registry/core/endpoint/etcd/etcd_test.go @@ -30,7 +30,12 @@ import ( func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "endpoints", + } return NewREST(restOptions), server } diff --git a/pkg/registry/core/event/etcd/etcd.go b/pkg/registry/core/event/etcd/etcd.go index 83ad778978..52164a5264 100644 --- a/pkg/registry/core/event/etcd/etcd.go +++ b/pkg/registry/core/event/etcd/etcd.go @@ -29,22 +29,20 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against events. -func NewREST(opts generic.RESTOptions, ttl uint64) *REST { - prefix := "/" + opts.ResourcePrefix +func NewREST(optsGetter generic.RESTOptionsGetter, ttl uint64) *REST { + resource := api.Resource("events") + opts, err := optsGetter.GetRESTOptions(resource) + if err != nil { + panic(err) // TODO: Propagate error up + } // We explicitly do NOT do any decoration here - switching on Cacher // for events will lead to too high memory consumption. - storageInterface, dFunc := generic.NewRawStorage(opts.StorageConfig) + opts.Decorator = generic.UndecoratedStorage // TODO use watchCacheSize=-1 to signal UndecoratedStorage store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.Event{} }, NewListFunc: func() runtime.Object { return &api.EventList{} }, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, id string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, id) - }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Event).Name, nil }, @@ -52,17 +50,15 @@ func NewREST(opts generic.RESTOptions, ttl uint64) *REST { TTLFunc: func(runtime.Object, uint64, bool) (uint64, error) { return ttl, nil }, - QualifiedResource: api.Resource("events"), - - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + QualifiedResource: resource, CreateStrategy: event.Strategy, UpdateStrategy: event.Strategy, DeleteStrategy: event.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: opts, AttrFunc: event.GetAttrs} // Pass in opts to use UndecoratedStorage + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} } diff --git a/pkg/registry/core/event/etcd/etcd_test.go b/pkg/registry/core/event/etcd/etcd_test.go index 1aa6a11dd6..6c8c1a4d04 100644 --- a/pkg/registry/core/event/etcd/etcd_test.go +++ b/pkg/registry/core/event/etcd/etcd_test.go @@ -30,7 +30,12 @@ var testTTL uint64 = 60 func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "events", + } return NewREST(restOptions, testTTL), server } diff --git a/pkg/registry/core/limitrange/etcd/BUILD b/pkg/registry/core/limitrange/etcd/BUILD index 2295457d81..8a7e04bdd2 100644 --- a/pkg/registry/core/limitrange/etcd/BUILD +++ b/pkg/registry/core/limitrange/etcd/BUILD @@ -16,12 +16,10 @@ go_library( tags = ["automanaged"], deps = [ "//pkg/api:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/limitrange:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/core/limitrange/etcd/etcd.go b/pkg/registry/core/limitrange/etcd/etcd.go index 86a46e4ad5..827167b272 100644 --- a/pkg/registry/core/limitrange/etcd/etcd.go +++ b/pkg/registry/core/limitrange/etcd/etcd.go @@ -18,12 +18,10 @@ package etcd import ( "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/limitrange" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) type REST struct { @@ -31,45 +29,24 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against horizontal pod autoscalers. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.LimitRangeList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.LimitRanges), - &api.LimitRange{}, - prefix, - limitrange.Strategy, - newListFunc, - limitrange.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.LimitRange{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, id string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, id) - }, + NewListFunc: func() runtime.Object { return &api.LimitRangeList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.LimitRange).Name, nil }, - PredicateFunc: limitrange.MatchLimitRange, - QualifiedResource: api.Resource("limitranges"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: limitrange.MatchLimitRange, + QualifiedResource: api.Resource("limitranges"), CreateStrategy: limitrange.Strategy, UpdateStrategy: limitrange.Strategy, DeleteStrategy: limitrange.Strategy, ExportStrategy: limitrange.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: limitrange.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} } diff --git a/pkg/registry/core/limitrange/etcd/etcd_test.go b/pkg/registry/core/limitrange/etcd/etcd_test.go index f20a26942a..2b9fa49e3a 100644 --- a/pkg/registry/core/limitrange/etcd/etcd_test.go +++ b/pkg/registry/core/limitrange/etcd/etcd_test.go @@ -31,7 +31,12 @@ import ( func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "limitranges", + } return NewREST(restOptions), server } diff --git a/pkg/registry/core/namespace/etcd/BUILD b/pkg/registry/core/namespace/etcd/BUILD index 0dad8f97d4..4e1823a109 100644 --- a/pkg/registry/core/namespace/etcd/BUILD +++ b/pkg/registry/core/namespace/etcd/BUILD @@ -20,7 +20,6 @@ go_library( "//pkg/api/errors/storage:go_default_library", "//pkg/api/rest:go_default_library", "//pkg/apis/meta/v1:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/namespace:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", diff --git a/pkg/registry/core/namespace/etcd/etcd.go b/pkg/registry/core/namespace/etcd/etcd.go index f28d372deb..051e5ea06e 100644 --- a/pkg/registry/core/namespace/etcd/etcd.go +++ b/pkg/registry/core/namespace/etcd/etcd.go @@ -24,7 +24,6 @@ import ( storageerr "k8s.io/kubernetes/pkg/api/errors/storage" "k8s.io/kubernetes/pkg/api/rest" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/namespace" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" @@ -49,45 +48,24 @@ type FinalizeREST struct { } // NewREST returns a RESTStorage object that will work against namespaces. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST, *FinalizeREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.NamespaceList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Namespaces), - &api.Namespace{}, - prefix, - namespace.Strategy, - newListFunc, - namespace.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *FinalizeREST) { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.Namespace{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return prefix - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NoNamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &api.NamespaceList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Namespace).Name, nil }, - PredicateFunc: namespace.MatchNamespace, - QualifiedResource: api.Resource("namespaces"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: namespace.MatchNamespace, + QualifiedResource: api.Resource("namespaces"), CreateStrategy: namespace.Strategy, UpdateStrategy: namespace.Strategy, DeleteStrategy: namespace.Strategy, ReturnDeletedObject: true, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: namespace.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } statusStore := *store diff --git a/pkg/registry/core/node/etcd/BUILD b/pkg/registry/core/node/etcd/BUILD index 42dff056bb..497f59dea4 100644 --- a/pkg/registry/core/node/etcd/BUILD +++ b/pkg/registry/core/node/etcd/BUILD @@ -20,7 +20,6 @@ go_library( "//pkg/api/v1:go_default_library", "//pkg/apis/meta/v1:go_default_library", "//pkg/kubelet/client:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/node:go_default_library", "//pkg/registry/core/node/rest:go_default_library", "//pkg/registry/generic:go_default_library", diff --git a/pkg/registry/core/node/etcd/etcd.go b/pkg/registry/core/node/etcd/etcd.go index 535e951265..750d62e339 100644 --- a/pkg/registry/core/node/etcd/etcd.go +++ b/pkg/registry/core/node/etcd/etcd.go @@ -26,7 +26,6 @@ import ( "k8s.io/kubernetes/pkg/api/v1" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/kubelet/client" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/node" noderest "k8s.io/kubernetes/pkg/registry/core/node/rest" "k8s.io/kubernetes/pkg/registry/generic" @@ -69,44 +68,24 @@ func (r *StatusREST) Update(ctx api.Context, name string, objInfo rest.UpdatedOb } // NewStorage returns a NodeStorage object that will work against nodes. -func NewStorage(opts generic.RESTOptions, kubeletClientConfig client.KubeletClientConfig, proxyTransport http.RoundTripper) (*NodeStorage, error) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.NodeList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Nodes), - &api.Node{}, - prefix, - node.Strategy, - newListFunc, - node.GetAttrs, - node.NodeNameTriggerFunc) - +func NewStorage(optsGetter generic.RESTOptionsGetter, kubeletClientConfig client.KubeletClientConfig, proxyTransport http.RoundTripper) (*NodeStorage, error) { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.Node{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return prefix - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NoNamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &api.NodeList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Node).Name, nil }, - PredicateFunc: node.MatchNode, - QualifiedResource: api.Resource("nodes"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: node.MatchNode, + QualifiedResource: api.Resource("nodes"), CreateStrategy: node.Strategy, UpdateStrategy: node.Strategy, DeleteStrategy: node.Strategy, ExportStrategy: node.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: node.GetAttrs, TriggerFunc: node.NodeNameTriggerFunc} + if err := store.CompleteWithOptions(options); err != nil { + return nil, err } statusStore := *store diff --git a/pkg/registry/core/node/etcd/etcd_test.go b/pkg/registry/core/node/etcd/etcd_test.go index d49d8f88f8..d6bf019fcb 100644 --- a/pkg/registry/core/node/etcd/etcd_test.go +++ b/pkg/registry/core/node/etcd/etcd_test.go @@ -32,7 +32,12 @@ import ( func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "nodes", + } storage, err := NewStorage(restOptions, kubeletclient.KubeletClientConfig{}, nil) if err != nil { t.Fatal(err) diff --git a/pkg/registry/core/persistentvolume/etcd/BUILD b/pkg/registry/core/persistentvolume/etcd/BUILD index 8e40ecb812..465de9686d 100644 --- a/pkg/registry/core/persistentvolume/etcd/BUILD +++ b/pkg/registry/core/persistentvolume/etcd/BUILD @@ -18,12 +18,10 @@ go_library( "//pkg/api:go_default_library", "//pkg/api/rest:go_default_library", "//pkg/apis/meta/v1:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/persistentvolume:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/core/persistentvolume/etcd/etcd.go b/pkg/registry/core/persistentvolume/etcd/etcd.go index 7bf94ef5b4..adefdad930 100644 --- a/pkg/registry/core/persistentvolume/etcd/etcd.go +++ b/pkg/registry/core/persistentvolume/etcd/etcd.go @@ -20,12 +20,10 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/rest" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/persistentvolume" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) type REST struct { @@ -33,45 +31,24 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against persistent volumes. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.PersistentVolumeList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.PersistentVolumes), - &api.PersistentVolume{}, - prefix, - persistentvolume.Strategy, - newListFunc, - persistentvolume.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.PersistentVolume{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return prefix - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NoNamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &api.PersistentVolumeList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.PersistentVolume).Name, nil }, - PredicateFunc: persistentvolume.MatchPersistentVolumes, - QualifiedResource: api.Resource("persistentvolumes"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: persistentvolume.MatchPersistentVolumes, + QualifiedResource: api.Resource("persistentvolumes"), CreateStrategy: persistentvolume.Strategy, UpdateStrategy: persistentvolume.Strategy, DeleteStrategy: persistentvolume.Strategy, ReturnDeletedObject: true, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: persistentvolume.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } statusStore := *store diff --git a/pkg/registry/core/persistentvolume/etcd/etcd_test.go b/pkg/registry/core/persistentvolume/etcd/etcd_test.go index fbce436788..7f9c23932c 100644 --- a/pkg/registry/core/persistentvolume/etcd/etcd_test.go +++ b/pkg/registry/core/persistentvolume/etcd/etcd_test.go @@ -34,7 +34,12 @@ import ( func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "persistentvolumes", + } persistentVolumeStorage, statusStorage := NewREST(restOptions) return persistentVolumeStorage, statusStorage, server } diff --git a/pkg/registry/core/persistentvolumeclaim/etcd/BUILD b/pkg/registry/core/persistentvolumeclaim/etcd/BUILD index 75c274ca86..fbabbe9972 100644 --- a/pkg/registry/core/persistentvolumeclaim/etcd/BUILD +++ b/pkg/registry/core/persistentvolumeclaim/etcd/BUILD @@ -18,12 +18,10 @@ go_library( "//pkg/api:go_default_library", "//pkg/api/rest:go_default_library", "//pkg/apis/meta/v1:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/persistentvolumeclaim:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/core/persistentvolumeclaim/etcd/etcd.go b/pkg/registry/core/persistentvolumeclaim/etcd/etcd.go index 1bd036e169..8e3171e4ae 100644 --- a/pkg/registry/core/persistentvolumeclaim/etcd/etcd.go +++ b/pkg/registry/core/persistentvolumeclaim/etcd/etcd.go @@ -20,12 +20,10 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/rest" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) type REST struct { @@ -33,45 +31,24 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against persistent volume claims. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.PersistentVolumeClaimList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.PersistentVolumeClaims), - &api.PersistentVolumeClaim{}, - prefix, - persistentvolumeclaim.Strategy, - newListFunc, - persistentvolumeclaim.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.PersistentVolumeClaim{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &api.PersistentVolumeClaimList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.PersistentVolumeClaim).Name, nil }, - PredicateFunc: persistentvolumeclaim.MatchPersistentVolumeClaim, - QualifiedResource: api.Resource("persistentvolumeclaims"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: persistentvolumeclaim.MatchPersistentVolumeClaim, + QualifiedResource: api.Resource("persistentvolumeclaims"), CreateStrategy: persistentvolumeclaim.Strategy, UpdateStrategy: persistentvolumeclaim.Strategy, DeleteStrategy: persistentvolumeclaim.Strategy, ReturnDeletedObject: true, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: persistentvolumeclaim.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } statusStore := *store diff --git a/pkg/registry/core/persistentvolumeclaim/etcd/etcd_test.go b/pkg/registry/core/persistentvolumeclaim/etcd/etcd_test.go index 6891c39a4d..afd9369235 100644 --- a/pkg/registry/core/persistentvolumeclaim/etcd/etcd_test.go +++ b/pkg/registry/core/persistentvolumeclaim/etcd/etcd_test.go @@ -34,7 +34,12 @@ import ( func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "persistentvolumeclaims", + } persistentVolumeClaimStorage, statusStorage := NewREST(restOptions) return persistentVolumeClaimStorage, statusStorage, server } diff --git a/pkg/registry/core/pod/etcd/BUILD b/pkg/registry/core/pod/etcd/BUILD index 9f1b8fd23d..cfeb0e9784 100644 --- a/pkg/registry/core/pod/etcd/BUILD +++ b/pkg/registry/core/pod/etcd/BUILD @@ -29,7 +29,6 @@ go_library( "//pkg/client/retry:go_default_library", "//pkg/kubelet/client:go_default_library", "//pkg/labels:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/pod:go_default_library", "//pkg/registry/core/pod/rest:go_default_library", "//pkg/registry/generic:go_default_library", diff --git a/pkg/registry/core/pod/etcd/etcd.go b/pkg/registry/core/pod/etcd/etcd.go index 9d9c897e86..118135a7b1 100644 --- a/pkg/registry/core/pod/etcd/etcd.go +++ b/pkg/registry/core/pod/etcd/etcd.go @@ -29,7 +29,6 @@ import ( metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" policyclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion" "k8s.io/kubernetes/pkg/kubelet/client" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/pod" podrest "k8s.io/kubernetes/pkg/registry/core/pod/rest" "k8s.io/kubernetes/pkg/registry/generic" @@ -58,45 +57,24 @@ type REST struct { } // NewStorage returns a RESTStorage object that will work against pods. -func NewStorage(opts generic.RESTOptions, k client.ConnectionInfoGetter, proxyTransport http.RoundTripper, podDisruptionBudgetClient policyclient.PodDisruptionBudgetsGetter) PodStorage { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.PodList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Pods), - &api.Pod{}, - prefix, - pod.Strategy, - newListFunc, - pod.GetAttrs, - pod.NodeNameTriggerFunc, - ) - +func NewStorage(optsGetter generic.RESTOptionsGetter, k client.ConnectionInfoGetter, proxyTransport http.RoundTripper, podDisruptionBudgetClient policyclient.PodDisruptionBudgetsGetter) PodStorage { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.Pod{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &api.PodList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Pod).Name, nil }, - PredicateFunc: pod.MatchPod, - QualifiedResource: api.Resource("pods"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: pod.MatchPod, + QualifiedResource: api.Resource("pods"), CreateStrategy: pod.Strategy, UpdateStrategy: pod.Strategy, DeleteStrategy: pod.Strategy, ReturnDeletedObject: true, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: pod.GetAttrs, TriggerFunc: pod.NodeNameTriggerFunc} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } statusStore := *store diff --git a/pkg/registry/core/pod/etcd/etcd_test.go b/pkg/registry/core/pod/etcd/etcd_test.go index b69149e6c5..5da86bf6ac 100644 --- a/pkg/registry/core/pod/etcd/etcd_test.go +++ b/pkg/registry/core/pod/etcd/etcd_test.go @@ -39,7 +39,12 @@ import ( func newStorage(t *testing.T) (*REST, *BindingREST, *StatusREST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 3} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 3, + ResourcePrefix: "pods", + } storage := NewStorage(restOptions, nil, nil, nil) return storage.Pod, storage.Binding, storage.Status, server } @@ -147,7 +152,12 @@ func (f FailDeletionStorage) Delete(ctx context.Context, key string, out runtime func newFailDeleteStorage(t *testing.T, called *bool) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 3} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 3, + ResourcePrefix: "pods", + } storage := NewStorage(restOptions, nil, nil, nil) storage.Pod.Store.Storage = FailDeletionStorage{storage.Pod.Store.Storage, called} return storage.Pod, server diff --git a/pkg/registry/core/podtemplate/etcd/BUILD b/pkg/registry/core/podtemplate/etcd/BUILD index 6dfb013c6c..b495b2452e 100644 --- a/pkg/registry/core/podtemplate/etcd/BUILD +++ b/pkg/registry/core/podtemplate/etcd/BUILD @@ -16,12 +16,10 @@ go_library( tags = ["automanaged"], deps = [ "//pkg/api:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/podtemplate:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/core/podtemplate/etcd/etcd.go b/pkg/registry/core/podtemplate/etcd/etcd.go index 8348de85d7..742a014f49 100644 --- a/pkg/registry/core/podtemplate/etcd/etcd.go +++ b/pkg/registry/core/podtemplate/etcd/etcd.go @@ -18,12 +18,10 @@ package etcd import ( "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/podtemplate" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) type REST struct { @@ -31,37 +29,15 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against pod templates. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.PodTemplateList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.PodTemplates), - &api.PodTemplate{}, - prefix, - podtemplate.Strategy, - newListFunc, - podtemplate.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.PodTemplate{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &api.PodTemplateList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.PodTemplate).Name, nil }, - PredicateFunc: podtemplate.MatchPodTemplate, - QualifiedResource: api.Resource("podtemplates"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: podtemplate.MatchPodTemplate, + QualifiedResource: api.Resource("podtemplates"), CreateStrategy: podtemplate.Strategy, UpdateStrategy: podtemplate.Strategy, @@ -69,9 +45,10 @@ func NewREST(opts generic.RESTOptions) *REST { ExportStrategy: podtemplate.Strategy, ReturnDeletedObject: true, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: podtemplate.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} } diff --git a/pkg/registry/core/podtemplate/etcd/etcd_test.go b/pkg/registry/core/podtemplate/etcd/etcd_test.go index 97b1e78438..ec36d07612 100644 --- a/pkg/registry/core/podtemplate/etcd/etcd_test.go +++ b/pkg/registry/core/podtemplate/etcd/etcd_test.go @@ -30,7 +30,12 @@ import ( func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "podtemplates", + } return NewREST(restOptions), server } diff --git a/pkg/registry/core/resourcequota/etcd/BUILD b/pkg/registry/core/resourcequota/etcd/BUILD index e268bbd327..81effb9805 100644 --- a/pkg/registry/core/resourcequota/etcd/BUILD +++ b/pkg/registry/core/resourcequota/etcd/BUILD @@ -18,12 +18,10 @@ go_library( "//pkg/api:go_default_library", "//pkg/api/rest:go_default_library", "//pkg/apis/meta/v1:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/resourcequota:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/core/resourcequota/etcd/etcd.go b/pkg/registry/core/resourcequota/etcd/etcd.go index a02982d9b8..88f9467041 100644 --- a/pkg/registry/core/resourcequota/etcd/etcd.go +++ b/pkg/registry/core/resourcequota/etcd/etcd.go @@ -20,12 +20,10 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/rest" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/resourcequota" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) type REST struct { @@ -33,45 +31,24 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against resource quotas. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.ResourceQuotaList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.ResourceQuotas), - &api.ResourceQuota{}, - prefix, - resourcequota.Strategy, - newListFunc, - resourcequota.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.ResourceQuota{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &api.ResourceQuotaList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.ResourceQuota).Name, nil }, - PredicateFunc: resourcequota.MatchResourceQuota, - QualifiedResource: api.Resource("resourcequotas"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: resourcequota.MatchResourceQuota, + QualifiedResource: api.Resource("resourcequotas"), CreateStrategy: resourcequota.Strategy, UpdateStrategy: resourcequota.Strategy, DeleteStrategy: resourcequota.Strategy, ReturnDeletedObject: true, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: resourcequota.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } statusStore := *store diff --git a/pkg/registry/core/resourcequota/etcd/etcd_test.go b/pkg/registry/core/resourcequota/etcd/etcd_test.go index c600e7443a..da12e30627 100644 --- a/pkg/registry/core/resourcequota/etcd/etcd_test.go +++ b/pkg/registry/core/resourcequota/etcd/etcd_test.go @@ -33,7 +33,12 @@ import ( func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "resourcequotas", + } resourceQuotaStorage, statusStorage := NewREST(restOptions) return resourceQuotaStorage, statusStorage, server } diff --git a/pkg/registry/core/rest/BUILD b/pkg/registry/core/rest/BUILD index 61490a1213..7c96b495ed 100644 --- a/pkg/registry/core/rest/BUILD +++ b/pkg/registry/core/rest/BUILD @@ -24,7 +24,6 @@ go_library( "//pkg/genericapiserver:go_default_library", "//pkg/kubelet/client:go_default_library", "//pkg/master/ports:go_default_library", - "//pkg/registry:go_default_library", "//pkg/registry/core/componentstatus:go_default_library", "//pkg/registry/core/configmap/etcd:go_default_library", "//pkg/registry/core/controller/etcd:go_default_library", @@ -48,6 +47,7 @@ go_library( "//pkg/registry/core/service/ipallocator:go_default_library", "//pkg/registry/core/service/portallocator:go_default_library", "//pkg/registry/core/serviceaccount/etcd:go_default_library", + "//pkg/registry/generic:go_default_library", "//pkg/runtime/schema:go_default_library", "//pkg/storage/etcd/util:go_default_library", "//pkg/util/net:go_default_library", diff --git a/pkg/registry/core/rest/storage_core.go b/pkg/registry/core/rest/storage_core.go index e10ba88306..f17f68ca66 100644 --- a/pkg/registry/core/rest/storage_core.go +++ b/pkg/registry/core/rest/storage_core.go @@ -36,7 +36,6 @@ import ( "k8s.io/kubernetes/pkg/genericapiserver" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/master/ports" - "k8s.io/kubernetes/pkg/registry" "k8s.io/kubernetes/pkg/registry/core/componentstatus" configmapetcd "k8s.io/kubernetes/pkg/registry/core/configmap/etcd" controlleretcd "k8s.io/kubernetes/pkg/registry/core/controller/etcd" @@ -57,9 +56,10 @@ import ( "k8s.io/kubernetes/pkg/registry/core/service/allocator" etcdallocator "k8s.io/kubernetes/pkg/registry/core/service/allocator/etcd" serviceetcd "k8s.io/kubernetes/pkg/registry/core/service/etcd" - ipallocator "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" + "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" "k8s.io/kubernetes/pkg/registry/core/service/portallocator" serviceaccountetcd "k8s.io/kubernetes/pkg/registry/core/serviceaccount/etcd" + "k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/runtime/schema" etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util" utilnet "k8s.io/kubernetes/pkg/util/net" @@ -89,7 +89,7 @@ type LegacyRESTStorage struct { ServiceNodePortAllocator rangeallocation.RangeRegistry } -func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter registry.RESTOptionsGetter) (LegacyRESTStorage, genericapiserver.APIGroupInfo, error) { +func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter generic.RESTOptionsGetter) (LegacyRESTStorage, genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *registered.GroupOrDie(api.GroupName), VersionedResourcesStorageMap: map[string]map[string]rest.Storage{}, @@ -114,36 +114,36 @@ func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter regist } restStorage := LegacyRESTStorage{} - podTemplateStorage := podtemplateetcd.NewREST(restOptionsGetter(api.Resource("podTemplates"))) + podTemplateStorage := podtemplateetcd.NewREST(restOptionsGetter) - eventStorage := eventetcd.NewREST(restOptionsGetter(api.Resource("events")), uint64(c.EventTTL.Seconds())) - limitRangeStorage := limitrangeetcd.NewREST(restOptionsGetter(api.Resource("limitRanges"))) + eventStorage := eventetcd.NewREST(restOptionsGetter, uint64(c.EventTTL.Seconds())) + limitRangeStorage := limitrangeetcd.NewREST(restOptionsGetter) - resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotaetcd.NewREST(restOptionsGetter(api.Resource("resourceQuotas"))) - secretStorage := secretetcd.NewREST(restOptionsGetter(api.Resource("secrets"))) - serviceAccountStorage := serviceaccountetcd.NewREST(restOptionsGetter(api.Resource("serviceAccounts"))) - persistentVolumeStorage, persistentVolumeStatusStorage := pvetcd.NewREST(restOptionsGetter(api.Resource("persistentVolumes"))) - persistentVolumeClaimStorage, persistentVolumeClaimStatusStorage := pvcetcd.NewREST(restOptionsGetter(api.Resource("persistentVolumeClaims"))) - configMapStorage := configmapetcd.NewREST(restOptionsGetter(api.Resource("configMaps"))) + resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotaetcd.NewREST(restOptionsGetter) + secretStorage := secretetcd.NewREST(restOptionsGetter) + serviceAccountStorage := serviceaccountetcd.NewREST(restOptionsGetter) + persistentVolumeStorage, persistentVolumeStatusStorage := pvetcd.NewREST(restOptionsGetter) + persistentVolumeClaimStorage, persistentVolumeClaimStatusStorage := pvcetcd.NewREST(restOptionsGetter) + configMapStorage := configmapetcd.NewREST(restOptionsGetter) - namespaceStorage, namespaceStatusStorage, namespaceFinalizeStorage := namespaceetcd.NewREST(restOptionsGetter(api.Resource("namespaces"))) + namespaceStorage, namespaceStatusStorage, namespaceFinalizeStorage := namespaceetcd.NewREST(restOptionsGetter) - endpointsStorage := endpointsetcd.NewREST(restOptionsGetter(api.Resource("endpoints"))) + endpointsStorage := endpointsetcd.NewREST(restOptionsGetter) endpointRegistry := endpoint.NewRegistry(endpointsStorage) - nodeStorage, err := nodeetcd.NewStorage(restOptionsGetter(api.Resource("nodes")), c.KubeletClientConfig, c.ProxyTransport) + nodeStorage, err := nodeetcd.NewStorage(restOptionsGetter, c.KubeletClientConfig, c.ProxyTransport) if err != nil { return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err } podStorage := podetcd.NewStorage( - restOptionsGetter(api.Resource("pods")), + restOptionsGetter, nodeStorage.KubeletConnectionInfo, c.ProxyTransport, podDisruptionClient, ) - serviceRESTStorage, serviceStatusStorage := serviceetcd.NewREST(restOptionsGetter(api.Resource("services"))) + serviceRESTStorage, serviceStatusStorage := serviceetcd.NewREST(restOptionsGetter) serviceRegistry := service.NewRegistry(serviceRESTStorage) var serviceClusterIPRegistry rangeallocation.RangeRegistry @@ -176,7 +176,7 @@ func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter regist }) restStorage.ServiceNodePortAllocator = serviceNodePortRegistry - controllerStorage := controlleretcd.NewStorage(restOptionsGetter(api.Resource("replicationControllers"))) + controllerStorage := controlleretcd.NewStorage(restOptionsGetter) serviceRest := service.NewStorage(serviceRegistry, endpointRegistry, ServiceClusterIPAllocator, ServiceNodePortAllocator, c.ProxyTransport) diff --git a/pkg/registry/core/secret/etcd/BUILD b/pkg/registry/core/secret/etcd/BUILD index fdac29d3c7..25e6f48ec5 100644 --- a/pkg/registry/core/secret/etcd/BUILD +++ b/pkg/registry/core/secret/etcd/BUILD @@ -16,12 +16,10 @@ go_library( tags = ["automanaged"], deps = [ "//pkg/api:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/secret:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/core/secret/etcd/etcd.go b/pkg/registry/core/secret/etcd/etcd.go index 104cd807bd..087d753cda 100644 --- a/pkg/registry/core/secret/etcd/etcd.go +++ b/pkg/registry/core/secret/etcd/etcd.go @@ -18,12 +18,10 @@ package etcd import ( "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/secret" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) type REST struct { @@ -31,44 +29,23 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against secrets. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.SecretList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Secrets), - &api.Secret{}, - prefix, - secret.Strategy, - newListFunc, - secret.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.Secret{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, id string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, id) - }, + NewListFunc: func() runtime.Object { return &api.SecretList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Secret).Name, nil }, - PredicateFunc: secret.Matcher, - QualifiedResource: api.Resource("secrets"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: secret.Matcher, + QualifiedResource: api.Resource("secrets"), CreateStrategy: secret.Strategy, UpdateStrategy: secret.Strategy, DeleteStrategy: secret.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: secret.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} } diff --git a/pkg/registry/core/secret/etcd/etcd_test.go b/pkg/registry/core/secret/etcd/etcd_test.go index 21fc72ab60..f270e8ee65 100644 --- a/pkg/registry/core/secret/etcd/etcd_test.go +++ b/pkg/registry/core/secret/etcd/etcd_test.go @@ -30,7 +30,12 @@ import ( func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "secrets", + } return NewREST(restOptions), server } diff --git a/pkg/registry/core/service/etcd/BUILD b/pkg/registry/core/service/etcd/BUILD index bfe543da34..1a4e7d1fa2 100644 --- a/pkg/registry/core/service/etcd/BUILD +++ b/pkg/registry/core/service/etcd/BUILD @@ -18,12 +18,10 @@ go_library( "//pkg/api:go_default_library", "//pkg/api/rest:go_default_library", "//pkg/apis/meta/v1:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/service:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/core/service/etcd/etcd.go b/pkg/registry/core/service/etcd/etcd.go index c0bc449425..72fd826071 100644 --- a/pkg/registry/core/service/etcd/etcd.go +++ b/pkg/registry/core/service/etcd/etcd.go @@ -20,12 +20,10 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/rest" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/service" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) type REST struct { @@ -33,46 +31,26 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against services. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.ServiceList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Services), - &api.Service{}, - prefix, - service.Strategy, - newListFunc, - service.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.Service{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &api.ServiceList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Service).Name, nil }, - PredicateFunc: service.MatchServices, - QualifiedResource: api.Resource("services"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: service.MatchServices, + QualifiedResource: api.Resource("services"), CreateStrategy: service.Strategy, UpdateStrategy: service.Strategy, DeleteStrategy: service.Strategy, ExportStrategy: service.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: service.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up + } + statusStore := *store statusStore.UpdateStrategy = service.StatusStrategy return &REST{store}, &StatusREST{store: &statusStore} diff --git a/pkg/registry/core/service/etcd/etcd_test.go b/pkg/registry/core/service/etcd/etcd_test.go index 003a34448d..cbd303eb53 100644 --- a/pkg/registry/core/service/etcd/etcd_test.go +++ b/pkg/registry/core/service/etcd/etcd_test.go @@ -31,7 +31,12 @@ import ( func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "services", + } serviceStorage, statusStorage := NewREST(restOptions) return serviceStorage, statusStorage, server } diff --git a/pkg/registry/core/serviceaccount/etcd/BUILD b/pkg/registry/core/serviceaccount/etcd/BUILD index 72b90452dd..153b0f2433 100644 --- a/pkg/registry/core/serviceaccount/etcd/BUILD +++ b/pkg/registry/core/serviceaccount/etcd/BUILD @@ -16,12 +16,10 @@ go_library( tags = ["automanaged"], deps = [ "//pkg/api:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/core/serviceaccount:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/core/serviceaccount/etcd/etcd.go b/pkg/registry/core/serviceaccount/etcd/etcd.go index f88908f3ab..6d20fb4749 100644 --- a/pkg/registry/core/serviceaccount/etcd/etcd.go +++ b/pkg/registry/core/serviceaccount/etcd/etcd.go @@ -18,12 +18,10 @@ package etcd import ( "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/core/serviceaccount" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) type REST struct { @@ -31,45 +29,24 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against service accounts. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &api.ServiceAccountList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.ServiceAccounts), - &api.ServiceAccount{}, - prefix, - serviceaccount.Strategy, - newListFunc, - serviceaccount.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.ServiceAccount{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &api.ServiceAccountList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.ServiceAccount).Name, nil }, - PredicateFunc: serviceaccount.Matcher, - QualifiedResource: api.Resource("serviceaccounts"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: serviceaccount.Matcher, + QualifiedResource: api.Resource("serviceaccounts"), CreateStrategy: serviceaccount.Strategy, UpdateStrategy: serviceaccount.Strategy, DeleteStrategy: serviceaccount.Strategy, ReturnDeletedObject: true, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: serviceaccount.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} } diff --git a/pkg/registry/core/serviceaccount/etcd/etcd_test.go b/pkg/registry/core/serviceaccount/etcd/etcd_test.go index 1fa2381a3d..7188d946dd 100644 --- a/pkg/registry/core/serviceaccount/etcd/etcd_test.go +++ b/pkg/registry/core/serviceaccount/etcd/etcd_test.go @@ -30,7 +30,12 @@ import ( func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "serviceaccounts", + } return NewREST(restOptions), server } diff --git a/pkg/registry/extensions/controller/etcd/etcd.go b/pkg/registry/extensions/controller/etcd/etcd.go index 8b947afb99..aec8ddea5f 100644 --- a/pkg/registry/extensions/controller/etcd/etcd.go +++ b/pkg/registry/extensions/controller/etcd/etcd.go @@ -39,9 +39,9 @@ type ContainerStorage struct { Scale *ScaleREST } -func NewStorage(opts generic.RESTOptions) ContainerStorage { +func NewStorage(optsGetter generic.RESTOptionsGetter) ContainerStorage { // scale does not set status, only updates spec so we ignore the status - controllerREST, _ := etcd.NewREST(opts) + controllerREST, _ := etcd.NewREST(optsGetter) rcRegistry := controller.NewRegistry(controllerREST) return ContainerStorage{ diff --git a/pkg/registry/extensions/daemonset/etcd/BUILD b/pkg/registry/extensions/daemonset/etcd/BUILD index 5754c1ede9..361a5bdde3 100644 --- a/pkg/registry/extensions/daemonset/etcd/BUILD +++ b/pkg/registry/extensions/daemonset/etcd/BUILD @@ -19,12 +19,10 @@ go_library( "//pkg/api/rest:go_default_library", "//pkg/apis/extensions:go_default_library", "//pkg/apis/meta/v1:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/extensions/daemonset:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/extensions/daemonset/etcd/etcd.go b/pkg/registry/extensions/daemonset/etcd/etcd.go index afeb8b9b47..304b2550e3 100644 --- a/pkg/registry/extensions/daemonset/etcd/etcd.go +++ b/pkg/registry/extensions/daemonset/etcd/etcd.go @@ -21,12 +21,10 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apis/extensions" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/extensions/daemonset" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // rest implements a RESTStorage for DaemonSets against etcd @@ -35,56 +33,25 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against DaemonSets. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &extensions.DaemonSetList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Daemonsets), - &extensions.DaemonSet{}, - prefix, - daemonset.Strategy, - newListFunc, - daemonset.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &extensions.DaemonSet{} }, - - // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a path that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - // Produces a path that etcd understands, to the resource by combining - // the namespace in the context with the given prefix - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, - // Retrieve the name field of a daemon set + NewFunc: func() runtime.Object { return &extensions.DaemonSet{} }, + NewListFunc: func() runtime.Object { return &extensions.DaemonSetList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*extensions.DaemonSet).Name, nil }, - // Used to match objects based on labels/fields for list and watch - PredicateFunc: daemonset.MatchDaemonSet, - QualifiedResource: extensions.Resource("daemonsets"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: daemonset.MatchDaemonSet, + QualifiedResource: extensions.Resource("daemonsets"), - // Used to validate daemon set creation CreateStrategy: daemonset.Strategy, - - // Used to validate daemon set updates UpdateStrategy: daemonset.Strategy, DeleteStrategy: daemonset.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: daemonset.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up + } + statusStore := *store statusStore.UpdateStrategy = daemonset.StatusStrategy diff --git a/pkg/registry/extensions/daemonset/etcd/etcd_test.go b/pkg/registry/extensions/daemonset/etcd/etcd_test.go index 254aefa46a..24c1a73620 100644 --- a/pkg/registry/extensions/daemonset/etcd/etcd_test.go +++ b/pkg/registry/extensions/daemonset/etcd/etcd_test.go @@ -32,7 +32,12 @@ import ( func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, extensions.GroupName) - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "daemonsets", + } daemonSetStorage, statusStorage := NewREST(restOptions) return daemonSetStorage, statusStorage, server } diff --git a/pkg/registry/extensions/deployment/etcd/BUILD b/pkg/registry/extensions/deployment/etcd/BUILD index bd4772aba8..aa7753b596 100644 --- a/pkg/registry/extensions/deployment/etcd/BUILD +++ b/pkg/registry/extensions/deployment/etcd/BUILD @@ -22,7 +22,6 @@ go_library( "//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions/validation:go_default_library", "//pkg/apis/meta/v1:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/extensions/deployment:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", diff --git a/pkg/registry/extensions/deployment/etcd/etcd.go b/pkg/registry/extensions/deployment/etcd/etcd.go index f32f5c37dd..18ba22208e 100644 --- a/pkg/registry/extensions/deployment/etcd/etcd.go +++ b/pkg/registry/extensions/deployment/etcd/etcd.go @@ -27,7 +27,6 @@ import ( "k8s.io/kubernetes/pkg/apis/extensions" extvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/extensions/deployment" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" @@ -43,8 +42,8 @@ type DeploymentStorage struct { Rollback *RollbackREST } -func NewStorage(opts generic.RESTOptions) DeploymentStorage { - deploymentRest, deploymentStatusRest, deploymentRollbackRest := NewREST(opts) +func NewStorage(optsGetter generic.RESTOptionsGetter) DeploymentStorage { + deploymentRest, deploymentStatusRest, deploymentRollbackRest := NewREST(optsGetter) deploymentRegistry := deployment.NewRegistry(deploymentRest) return DeploymentStorage{ @@ -60,55 +59,25 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against deployments. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST, *RollbackREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &extensions.DeploymentList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Deployments), - &extensions.Deployment{}, - prefix, - deployment.Strategy, - newListFunc, - deployment.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *RollbackREST) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &extensions.Deployment{} }, - // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a path that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix. - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - // Produces a path that etcd understands, to the resource by combining - // the namespace in the context with the given prefix. - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, - // Retrieve the name field of a deployment. + NewFunc: func() runtime.Object { return &extensions.Deployment{} }, + NewListFunc: func() runtime.Object { return &extensions.DeploymentList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*extensions.Deployment).Name, nil }, - // Used to match objects based on labels/fields for list. - PredicateFunc: deployment.MatchDeployment, - QualifiedResource: extensions.Resource("deployments"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: deployment.MatchDeployment, + QualifiedResource: extensions.Resource("deployments"), - // Used to validate deployment creation. CreateStrategy: deployment.Strategy, - - // Used to validate deployment updates. UpdateStrategy: deployment.Strategy, DeleteStrategy: deployment.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: deployment.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up + } + statusStore := *store statusStore.UpdateStrategy = deployment.StatusStrategy return &REST{store}, &StatusREST{store: &statusStore}, &RollbackREST{store: store} diff --git a/pkg/registry/extensions/ingress/etcd/BUILD b/pkg/registry/extensions/ingress/etcd/BUILD index 07ed4ac575..8113a38ac6 100644 --- a/pkg/registry/extensions/ingress/etcd/BUILD +++ b/pkg/registry/extensions/ingress/etcd/BUILD @@ -19,12 +19,10 @@ go_library( "//pkg/api/rest:go_default_library", "//pkg/apis/extensions:go_default_library", "//pkg/apis/meta/v1:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/extensions/ingress:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/extensions/ingress/etcd/etcd.go b/pkg/registry/extensions/ingress/etcd/etcd.go index 3cd9b2dc0c..f0652ec66f 100644 --- a/pkg/registry/extensions/ingress/etcd/etcd.go +++ b/pkg/registry/extensions/ingress/etcd/etcd.go @@ -21,12 +21,10 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apis/extensions" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/registry/cachesize" - ingress "k8s.io/kubernetes/pkg/registry/extensions/ingress" + "k8s.io/kubernetes/pkg/registry/extensions/ingress" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // rest implements a RESTStorage for replication controllers against etcd @@ -35,56 +33,25 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against replication controllers. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &extensions.IngressList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Ingress), - &extensions.Ingress{}, - prefix, - ingress.Strategy, - newListFunc, - ingress.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &extensions.Ingress{} }, - - // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a ingress that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - // Produces a ingress that etcd understands, to the resource by combining - // the namespace in the context with the given prefix - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, - // Retrieve the name field of a replication controller + NewFunc: func() runtime.Object { return &extensions.Ingress{} }, + NewListFunc: func() runtime.Object { return &extensions.IngressList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*extensions.Ingress).Name, nil }, - // Used to match objects based on labels/fields for list and watch - PredicateFunc: ingress.MatchIngress, - QualifiedResource: extensions.Resource("ingresses"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: ingress.MatchIngress, + QualifiedResource: extensions.Resource("ingresses"), - // Used to validate controller creation CreateStrategy: ingress.Strategy, - - // Used to validate controller updates UpdateStrategy: ingress.Strategy, DeleteStrategy: ingress.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: ingress.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up + } + statusStore := *store statusStore.UpdateStrategy = ingress.StatusStrategy return &REST{store}, &StatusREST{store: &statusStore} diff --git a/pkg/registry/extensions/ingress/etcd/etcd_test.go b/pkg/registry/extensions/ingress/etcd/etcd_test.go index 7828d8a654..a7b30c61df 100644 --- a/pkg/registry/extensions/ingress/etcd/etcd_test.go +++ b/pkg/registry/extensions/ingress/etcd/etcd_test.go @@ -32,7 +32,12 @@ import ( func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, extensions.GroupName) - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "ingresses", + } ingressStorage, statusStorage := NewREST(restOptions) return ingressStorage, statusStorage, server } diff --git a/pkg/registry/extensions/networkpolicy/etcd/BUILD b/pkg/registry/extensions/networkpolicy/etcd/BUILD index 1b372b1880..f402819afb 100644 --- a/pkg/registry/extensions/networkpolicy/etcd/BUILD +++ b/pkg/registry/extensions/networkpolicy/etcd/BUILD @@ -15,14 +15,11 @@ go_library( srcs = ["etcd.go"], tags = ["automanaged"], deps = [ - "//pkg/api:go_default_library", "//pkg/apis/extensions:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/extensions/networkpolicy:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/extensions/networkpolicy/etcd/etcd.go b/pkg/registry/extensions/networkpolicy/etcd/etcd.go index db610f822a..c0fdd4eb92 100644 --- a/pkg/registry/extensions/networkpolicy/etcd/etcd.go +++ b/pkg/registry/extensions/networkpolicy/etcd/etcd.go @@ -17,14 +17,11 @@ limitations under the License. package etcd import ( - "k8s.io/kubernetes/pkg/api" extensionsapi "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/extensions/networkpolicy" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // rest implements a RESTStorage for network policies against etcd @@ -33,55 +30,23 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against network policies. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &extensionsapi.NetworkPolicyList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.NetworkPolicys), - &extensionsapi.NetworkPolicy{}, - prefix, - networkpolicy.Strategy, - newListFunc, - networkpolicy.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &extensionsapi.NetworkPolicy{} }, - - // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a NetworkPolicy that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - // Produces a NetworkPolicy that etcd understands, to the resource by combining - // the namespace in the context with the given prefix - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, - // Retrieve the name field of a network policy + NewFunc: func() runtime.Object { return &extensionsapi.NetworkPolicy{} }, + NewListFunc: func() runtime.Object { return &extensionsapi.NetworkPolicyList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*extensionsapi.NetworkPolicy).Name, nil }, - // Used to match objects based on labels/fields for list and watch - PredicateFunc: networkpolicy.MatchNetworkPolicy, - QualifiedResource: extensionsapi.Resource("networkpolicies"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: networkpolicy.MatchNetworkPolicy, + QualifiedResource: extensionsapi.Resource("networkpolicies"), - // Used to validate controller creation CreateStrategy: networkpolicy.Strategy, - - // Used to validate controller updates UpdateStrategy: networkpolicy.Strategy, DeleteStrategy: networkpolicy.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: networkpolicy.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} } diff --git a/pkg/registry/extensions/networkpolicy/etcd/etcd_test.go b/pkg/registry/extensions/networkpolicy/etcd/etcd_test.go index b7097e6db8..d4cd8849e2 100644 --- a/pkg/registry/extensions/networkpolicy/etcd/etcd_test.go +++ b/pkg/registry/extensions/networkpolicy/etcd/etcd_test.go @@ -33,7 +33,12 @@ import ( func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "extensions") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "networkpolicies", + } return NewREST(restOptions), server } diff --git a/pkg/registry/extensions/podsecuritypolicy/etcd/BUILD b/pkg/registry/extensions/podsecuritypolicy/etcd/BUILD index 48e5ff0d97..c148ed2e00 100644 --- a/pkg/registry/extensions/podsecuritypolicy/etcd/BUILD +++ b/pkg/registry/extensions/podsecuritypolicy/etcd/BUILD @@ -15,14 +15,11 @@ go_library( srcs = ["etcd.go"], tags = ["automanaged"], deps = [ - "//pkg/api:go_default_library", "//pkg/apis/extensions:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/extensions/podsecuritypolicy:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/extensions/podsecuritypolicy/etcd/etcd.go b/pkg/registry/extensions/podsecuritypolicy/etcd/etcd.go index 504d390397..af528b8738 100644 --- a/pkg/registry/extensions/podsecuritypolicy/etcd/etcd.go +++ b/pkg/registry/extensions/podsecuritypolicy/etcd/etcd.go @@ -17,14 +17,11 @@ limitations under the License. package etcd import ( - "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // REST implements a RESTStorage for PodSecurityPolicies against etcd. @@ -33,44 +30,24 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against PodSecurityPolicy objects. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &extensions.PodSecurityPolicyList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.PodSecurityPolicies), - &extensions.PodSecurityPolicy{}, - prefix, - podsecuritypolicy.Strategy, - newListFunc, - podsecuritypolicy.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &extensions.PodSecurityPolicy{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return prefix - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NoNamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &extensions.PodSecurityPolicyList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*extensions.PodSecurityPolicy).Name, nil }, - PredicateFunc: podsecuritypolicy.MatchPodSecurityPolicy, - QualifiedResource: extensions.Resource("podsecuritypolicies"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: podsecuritypolicy.MatchPodSecurityPolicy, + QualifiedResource: extensions.Resource("podsecuritypolicies"), CreateStrategy: podsecuritypolicy.Strategy, UpdateStrategy: podsecuritypolicy.Strategy, DeleteStrategy: podsecuritypolicy.Strategy, ReturnDeletedObject: true, - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: podsecuritypolicy.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} } diff --git a/pkg/registry/extensions/podsecuritypolicy/etcd/etcd_test.go b/pkg/registry/extensions/podsecuritypolicy/etcd/etcd_test.go index 5dba2a05cf..f845dabec4 100644 --- a/pkg/registry/extensions/podsecuritypolicy/etcd/etcd_test.go +++ b/pkg/registry/extensions/podsecuritypolicy/etcd/etcd_test.go @@ -33,7 +33,12 @@ import ( func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "extensions") - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "podsecuritypolicies", + } return NewREST(restOptions), server } diff --git a/pkg/registry/extensions/replicaset/etcd/BUILD b/pkg/registry/extensions/replicaset/etcd/BUILD index 8b44db3bb0..cc82c528c1 100644 --- a/pkg/registry/extensions/replicaset/etcd/BUILD +++ b/pkg/registry/extensions/replicaset/etcd/BUILD @@ -21,12 +21,10 @@ go_library( "//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions/validation:go_default_library", "//pkg/apis/meta/v1:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/extensions/replicaset:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/extensions/replicaset/etcd/etcd.go b/pkg/registry/extensions/replicaset/etcd/etcd.go index d7601b2109..7135a522b7 100644 --- a/pkg/registry/extensions/replicaset/etcd/etcd.go +++ b/pkg/registry/extensions/replicaset/etcd/etcd.go @@ -27,12 +27,10 @@ import ( "k8s.io/kubernetes/pkg/apis/extensions" extvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/extensions/replicaset" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // ReplicaSetStorage includes dummy storage for ReplicaSets and for Scale subresource. @@ -42,8 +40,8 @@ type ReplicaSetStorage struct { Scale *ScaleREST } -func NewStorage(opts generic.RESTOptions) ReplicaSetStorage { - replicaSetRest, replicaSetStatusRest := NewREST(opts) +func NewStorage(optsGetter generic.RESTOptionsGetter) ReplicaSetStorage { + replicaSetRest, replicaSetStatusRest := NewREST(optsGetter) replicaSetRegistry := replicaset.NewRegistry(replicaSetRest) return ReplicaSetStorage{ @@ -58,56 +56,25 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against ReplicaSet. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &extensions.ReplicaSetList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Replicasets), - &extensions.ReplicaSet{}, - prefix, - replicaset.Strategy, - newListFunc, - replicaset.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &extensions.ReplicaSet{} }, - - // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a path that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - // Produces a path that etcd understands, to the resource by combining - // the namespace in the context with the given prefix - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, - // Retrieve the name field of a ReplicaSet + NewFunc: func() runtime.Object { return &extensions.ReplicaSet{} }, + NewListFunc: func() runtime.Object { return &extensions.ReplicaSetList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*extensions.ReplicaSet).Name, nil }, - // Used to match objects based on labels/fields for list and watch - PredicateFunc: replicaset.MatchReplicaSet, - QualifiedResource: api.Resource("replicasets"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: replicaset.MatchReplicaSet, + QualifiedResource: extensions.Resource("replicasets"), - // Used to validate ReplicaSet creation CreateStrategy: replicaset.Strategy, - - // Used to validate ReplicaSet updates UpdateStrategy: replicaset.Strategy, DeleteStrategy: replicaset.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: replicaset.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up + } + statusStore := *store statusStore.UpdateStrategy = replicaset.StatusStrategy diff --git a/pkg/registry/extensions/rest/BUILD b/pkg/registry/extensions/rest/BUILD index 661794d0fa..927eb20a92 100644 --- a/pkg/registry/extensions/rest/BUILD +++ b/pkg/registry/extensions/rest/BUILD @@ -24,7 +24,6 @@ go_library( "//pkg/apis/extensions/v1beta1:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:go_default_library", "//pkg/genericapiserver:go_default_library", - "//pkg/registry:go_default_library", "//pkg/registry/autoscaling/horizontalpodautoscaler/etcd:go_default_library", "//pkg/registry/batch/job/etcd:go_default_library", "//pkg/registry/extensions/controller/etcd:go_default_library", @@ -36,6 +35,7 @@ go_library( "//pkg/registry/extensions/replicaset/etcd:go_default_library", "//pkg/registry/extensions/thirdpartyresource/etcd:go_default_library", "//pkg/registry/extensions/thirdpartyresourcedata:go_default_library", + "//pkg/registry/generic:go_default_library", "//pkg/runtime:go_default_library", "//pkg/util/runtime:go_default_library", "//pkg/util/sets:go_default_library", diff --git a/pkg/registry/extensions/rest/storage_extensions.go b/pkg/registry/extensions/rest/storage_extensions.go index 70499508ad..f215c019b2 100644 --- a/pkg/registry/extensions/rest/storage_extensions.go +++ b/pkg/registry/extensions/rest/storage_extensions.go @@ -22,13 +22,11 @@ import ( "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apis/extensions" extensionsapiv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion" "k8s.io/kubernetes/pkg/genericapiserver" - "k8s.io/kubernetes/pkg/registry" horizontalpodautoscaleretcd "k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/etcd" jobetcd "k8s.io/kubernetes/pkg/registry/batch/job/etcd" expcontrolleretcd "k8s.io/kubernetes/pkg/registry/extensions/controller/etcd" @@ -39,6 +37,7 @@ import ( pspetcd "k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/etcd" replicasetetcd "k8s.io/kubernetes/pkg/registry/extensions/replicaset/etcd" thirdpartyresourceetcd "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresource/etcd" + "k8s.io/kubernetes/pkg/registry/generic" utilruntime "k8s.io/kubernetes/pkg/util/runtime" "k8s.io/kubernetes/pkg/util/wait" ) @@ -47,7 +46,7 @@ type RESTStorageProvider struct { ResourceInterface ResourceInterface } -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(extensions.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) { @@ -58,59 +57,59 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapise return apiGroupInfo, true } -func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { version := extensionsapiv1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} if apiResourceConfigSource.ResourceEnabled(version.WithResource("horizontalpodautoscalers")) { - hpaStorage, hpaStatusStorage := horizontalpodautoscaleretcd.NewREST(restOptionsGetter(extensions.Resource("horizontalpodautoscalers"))) + hpaStorage, hpaStatusStorage := horizontalpodautoscaleretcd.NewREST(restOptionsGetter) storage["horizontalpodautoscalers"] = hpaStorage storage["horizontalpodautoscalers/status"] = hpaStatusStorage - controllerStorage := expcontrolleretcd.NewStorage(restOptionsGetter(api.Resource("replicationControllers"))) + controllerStorage := expcontrolleretcd.NewStorage(restOptionsGetter) storage["replicationcontrollers"] = controllerStorage.ReplicationController storage["replicationcontrollers/scale"] = controllerStorage.Scale } if apiResourceConfigSource.ResourceEnabled(version.WithResource("thirdpartyresources")) { - thirdPartyResourceStorage := thirdpartyresourceetcd.NewREST(restOptionsGetter(extensions.Resource("thirdpartyresources"))) + thirdPartyResourceStorage := thirdpartyresourceetcd.NewREST(restOptionsGetter) storage["thirdpartyresources"] = thirdPartyResourceStorage } if apiResourceConfigSource.ResourceEnabled(version.WithResource("daemonsets")) { - daemonSetStorage, daemonSetStatusStorage := daemonetcd.NewREST(restOptionsGetter(extensions.Resource("daemonsets"))) + daemonSetStorage, daemonSetStatusStorage := daemonetcd.NewREST(restOptionsGetter) storage["daemonsets"] = daemonSetStorage storage["daemonsets/status"] = daemonSetStatusStorage } if apiResourceConfigSource.ResourceEnabled(version.WithResource("deployments")) { - deploymentStorage := deploymentetcd.NewStorage(restOptionsGetter(extensions.Resource("deployments"))) + deploymentStorage := deploymentetcd.NewStorage(restOptionsGetter) storage["deployments"] = deploymentStorage.Deployment storage["deployments/status"] = deploymentStorage.Status storage["deployments/rollback"] = deploymentStorage.Rollback storage["deployments/scale"] = deploymentStorage.Scale } if apiResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) { - jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter(extensions.Resource("jobs"))) + jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter) storage["jobs"] = jobsStorage storage["jobs/status"] = jobsStatusStorage } if apiResourceConfigSource.ResourceEnabled(version.WithResource("ingresses")) { - ingressStorage, ingressStatusStorage := ingressetcd.NewREST(restOptionsGetter(extensions.Resource("ingresses"))) + ingressStorage, ingressStatusStorage := ingressetcd.NewREST(restOptionsGetter) storage["ingresses"] = ingressStorage storage["ingresses/status"] = ingressStatusStorage } - if apiResourceConfigSource.ResourceEnabled(version.WithResource("podsecuritypolicy")) { - podSecurityExtensionsStorage := pspetcd.NewREST(restOptionsGetter(extensions.Resource("podsecuritypolicy"))) + if apiResourceConfigSource.ResourceEnabled(version.WithResource("podsecuritypolicy")) || apiResourceConfigSource.ResourceEnabled(version.WithResource("podsecuritypolicies")) { + podSecurityExtensionsStorage := pspetcd.NewREST(restOptionsGetter) storage["podSecurityPolicies"] = podSecurityExtensionsStorage } if apiResourceConfigSource.ResourceEnabled(version.WithResource("replicasets")) { - replicaSetStorage := replicasetetcd.NewStorage(restOptionsGetter(extensions.Resource("replicasets"))) + replicaSetStorage := replicasetetcd.NewStorage(restOptionsGetter) storage["replicasets"] = replicaSetStorage.ReplicaSet storage["replicasets/status"] = replicaSetStorage.Status storage["replicasets/scale"] = replicaSetStorage.Scale } if apiResourceConfigSource.ResourceEnabled(version.WithResource("networkpolicies")) { - networkExtensionsStorage := networkpolicyetcd.NewREST(restOptionsGetter(extensions.Resource("networkpolicies"))) + networkExtensionsStorage := networkpolicyetcd.NewREST(restOptionsGetter) storage["networkpolicies"] = networkExtensionsStorage } diff --git a/pkg/registry/extensions/thirdpartyresource/etcd/BUILD b/pkg/registry/extensions/thirdpartyresource/etcd/BUILD index 838c0b9661..ae42033a17 100644 --- a/pkg/registry/extensions/thirdpartyresource/etcd/BUILD +++ b/pkg/registry/extensions/thirdpartyresource/etcd/BUILD @@ -15,7 +15,6 @@ go_library( srcs = ["etcd.go"], tags = ["automanaged"], deps = [ - "//pkg/api:go_default_library", "//pkg/apis/extensions:go_default_library", "//pkg/registry/extensions/thirdpartyresource:go_default_library", "//pkg/registry/generic:go_default_library", diff --git a/pkg/registry/extensions/thirdpartyresource/etcd/etcd.go b/pkg/registry/extensions/thirdpartyresource/etcd/etcd.go index f147e97903..d5d7e31726 100644 --- a/pkg/registry/extensions/thirdpartyresource/etcd/etcd.go +++ b/pkg/registry/extensions/thirdpartyresource/etcd/etcd.go @@ -17,7 +17,6 @@ limitations under the License. package etcd import ( - "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresource" "k8s.io/kubernetes/pkg/registry/generic" @@ -31,35 +30,32 @@ type REST struct { } // NewREST returns a registry which will store ThirdPartyResource in the given helper -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { + resource := extensions.Resource("thirdpartyresources") + opts, err := optsGetter.GetRESTOptions(resource) + if err != nil { + panic(err) // TODO: Propagate error up + } - // We explicitly do NOT do any decoration here yet. - storageInterface, dFunc := generic.NewRawStorage(opts.StorageConfig) + // We explicitly do NOT do any decoration here yet. // TODO determine why we do not want to cache here + opts.Decorator = generic.UndecoratedStorage // TODO use watchCacheSize=-1 to signal UndecoratedStorage store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &extensions.ThirdPartyResource{} }, NewListFunc: func() runtime.Object { return &extensions.ThirdPartyResourceList{} }, - KeyRootFunc: func(ctx api.Context) string { - return prefix - }, - KeyFunc: func(ctx api.Context, id string) (string, error) { - return genericregistry.NoNamespaceKeyFunc(ctx, prefix, id) - }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*extensions.ThirdPartyResource).Name, nil }, - PredicateFunc: thirdpartyresource.Matcher, - QualifiedResource: extensions.Resource("thirdpartyresources"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, - CreateStrategy: thirdpartyresource.Strategy, - UpdateStrategy: thirdpartyresource.Strategy, - DeleteStrategy: thirdpartyresource.Strategy, + PredicateFunc: thirdpartyresource.Matcher, + QualifiedResource: resource, - Storage: storageInterface, - DestroyFunc: dFunc, + CreateStrategy: thirdpartyresource.Strategy, + UpdateStrategy: thirdpartyresource.Strategy, + DeleteStrategy: thirdpartyresource.Strategy, + } + options := &generic.StoreOptions{RESTOptions: opts, AttrFunc: thirdpartyresource.GetAttrs} // Pass in opts to use UndecoratedStorage + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } - return &REST{store} } diff --git a/pkg/registry/extensions/thirdpartyresource/etcd/etcd_test.go b/pkg/registry/extensions/thirdpartyresource/etcd/etcd_test.go index 0a26b6b20b..6f326a99ad 100644 --- a/pkg/registry/extensions/thirdpartyresource/etcd/etcd_test.go +++ b/pkg/registry/extensions/thirdpartyresource/etcd/etcd_test.go @@ -34,7 +34,12 @@ import ( func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, extensions.GroupName) - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "thirdpartyresources", + } return NewREST(restOptions), server } diff --git a/pkg/registry/extensions/thirdpartyresourcedata/etcd/BUILD b/pkg/registry/extensions/thirdpartyresourcedata/etcd/BUILD index 3d42fd7a91..42084f0585 100644 --- a/pkg/registry/extensions/thirdpartyresourcedata/etcd/BUILD +++ b/pkg/registry/extensions/thirdpartyresourcedata/etcd/BUILD @@ -15,7 +15,6 @@ go_library( srcs = ["etcd.go"], tags = ["automanaged"], deps = [ - "//pkg/api:go_default_library", "//pkg/apis/extensions:go_default_library", "//pkg/registry/extensions/thirdpartyresourcedata:go_default_library", "//pkg/registry/generic:go_default_library", diff --git a/pkg/registry/extensions/thirdpartyresourcedata/etcd/etcd.go b/pkg/registry/extensions/thirdpartyresourcedata/etcd/etcd.go index 7ce3d611a6..f3d36a5c9a 100644 --- a/pkg/registry/extensions/thirdpartyresourcedata/etcd/etcd.go +++ b/pkg/registry/extensions/thirdpartyresourcedata/etcd/etcd.go @@ -19,7 +19,6 @@ package etcd import ( "strings" - "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata" "k8s.io/kubernetes/pkg/registry/generic" @@ -34,34 +33,33 @@ type REST struct { } // NewREST returns a registry which will store ThirdPartyResourceData in the given helper -func NewREST(opts generic.RESTOptions, group, kind string) *REST { - prefix := "/ThirdPartyResourceData/" + group + "/" + strings.ToLower(kind) + "s" +func NewREST(optsGetter generic.RESTOptionsGetter, group, kind string) *REST { + resource := extensions.Resource("thirdpartyresourcedatas") + opts, err := optsGetter.GetRESTOptions(resource) + if err != nil { + panic(err) // TODO: Propagate error up + } // We explicitly do NOT do any decoration here yet. - storageInterface, dFunc := generic.NewRawStorage(opts.StorageConfig) + opts.Decorator = generic.UndecoratedStorage // TODO use watchCacheSize=-1 to signal UndecoratedStorage + opts.ResourcePrefix = "/ThirdPartyResourceData/" + group + "/" + strings.ToLower(kind) + "s" store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &extensions.ThirdPartyResourceData{} }, NewListFunc: func() runtime.Object { return &extensions.ThirdPartyResourceDataList{} }, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, id string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, id) - }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*extensions.ThirdPartyResourceData).Name, nil }, - PredicateFunc: thirdpartyresourcedata.Matcher, - QualifiedResource: extensions.Resource("thirdpartyresourcedatas"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, - CreateStrategy: thirdpartyresourcedata.Strategy, - UpdateStrategy: thirdpartyresourcedata.Strategy, - DeleteStrategy: thirdpartyresourcedata.Strategy, + PredicateFunc: thirdpartyresourcedata.Matcher, + QualifiedResource: resource, - Storage: storageInterface, - DestroyFunc: dFunc, + CreateStrategy: thirdpartyresourcedata.Strategy, + UpdateStrategy: thirdpartyresourcedata.Strategy, + DeleteStrategy: thirdpartyresourcedata.Strategy, + } + options := &generic.StoreOptions{RESTOptions: opts, AttrFunc: thirdpartyresourcedata.GetAttrs} // Pass in opts to use UndecoratedStorage and custom ResourcePrefix + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{ diff --git a/pkg/registry/generic/BUILD b/pkg/registry/generic/BUILD index 9284621128..bf3c9d14db 100644 --- a/pkg/registry/generic/BUILD +++ b/pkg/registry/generic/BUILD @@ -21,10 +21,9 @@ go_library( tags = ["automanaged"], deps = [ "//pkg/api:go_default_library", - "//pkg/api/rest:go_default_library", "//pkg/fields:go_default_library", - "//pkg/labels:go_default_library", "//pkg/runtime:go_default_library", + "//pkg/runtime/schema:go_default_library", "//pkg/storage:go_default_library", "//pkg/storage/storagebackend:go_default_library", "//pkg/storage/storagebackend/factory:go_default_library", diff --git a/pkg/registry/generic/options.go b/pkg/registry/generic/options.go index 73f7db9c23..8f53fc6133 100644 --- a/pkg/registry/generic/options.go +++ b/pkg/registry/generic/options.go @@ -17,6 +17,8 @@ limitations under the License. package generic import ( + "k8s.io/kubernetes/pkg/runtime/schema" + "k8s.io/kubernetes/pkg/storage" "k8s.io/kubernetes/pkg/storage/storagebackend" ) @@ -29,3 +31,19 @@ type RESTOptions struct { DeleteCollectionWorkers int ResourcePrefix string } + +// Implement RESTOptionsGetter so that RESTOptions can directly be used when available (i.e. tests) +func (opts RESTOptions) GetRESTOptions(schema.GroupResource) (RESTOptions, error) { + return opts, nil +} + +type RESTOptionsGetter interface { + GetRESTOptions(resource schema.GroupResource) (RESTOptions, error) +} + +// StoreOptions is set of configuration options used to complete generic registries. +type StoreOptions struct { + RESTOptions RESTOptionsGetter + TriggerFunc storage.TriggerPublisherFunc + AttrFunc storage.AttrFunc +} diff --git a/pkg/registry/generic/registry/BUILD b/pkg/registry/generic/registry/BUILD index e2dc9c689b..26ebe43549 100644 --- a/pkg/registry/generic/registry/BUILD +++ b/pkg/registry/generic/registry/BUILD @@ -29,6 +29,7 @@ go_library( "//pkg/apis/meta/v1:go_default_library", "//pkg/fields:go_default_library", "//pkg/labels:go_default_library", + "//pkg/registry/cachesize:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/runtime:go_default_library", "//pkg/runtime/schema:go_default_library", diff --git a/pkg/registry/generic/registry/storage_factory.go b/pkg/registry/generic/registry/storage_factory.go index 135b25aa46..5166a35c5b 100644 --- a/pkg/registry/generic/registry/storage_factory.go +++ b/pkg/registry/generic/registry/storage_factory.go @@ -17,9 +17,6 @@ limitations under the License. package registry import ( - "k8s.io/kubernetes/pkg/api/rest" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/storage" @@ -34,9 +31,9 @@ func StorageWithCacher( capacity int, objectType runtime.Object, resourcePrefix string, - scopeStrategy rest.NamespaceScopedStrategy, + keyFunc func(obj runtime.Object) (string, error), newListFunc func() runtime.Object, - getAttrsFunc func(runtime.Object) (labels.Set, fields.Set, error), + getAttrsFunc storage.AttrFunc, triggerFunc storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc) { s, d := generic.NewRawStorage(storageConfig) @@ -48,20 +45,12 @@ func StorageWithCacher( Versioner: etcdstorage.APIObjectVersioner{}, Type: objectType, ResourcePrefix: resourcePrefix, + KeyFunc: keyFunc, NewListFunc: newListFunc, GetAttrsFunc: getAttrsFunc, TriggerPublisherFunc: triggerFunc, Codec: storageConfig.Codec, } - if scopeStrategy.NamespaceScoped() { - cacherConfig.KeyFunc = func(obj runtime.Object) (string, error) { - return storage.NamespaceKeyFunc(resourcePrefix, obj) - } - } else { - cacherConfig.KeyFunc = func(obj runtime.Object) (string, error) { - return storage.NoNamespaceKeyFunc(resourcePrefix, obj) - } - } cacher := storage.NewCacherFromConfig(cacherConfig) destroyFunc := func() { cacher.Stop() diff --git a/pkg/registry/generic/registry/store.go b/pkg/registry/generic/registry/store.go index 61d8a9f2e6..89758e0825 100644 --- a/pkg/registry/generic/registry/store.go +++ b/pkg/registry/generic/registry/store.go @@ -32,6 +32,8 @@ import ( metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/labels" + "k8s.io/kubernetes/pkg/registry/cachesize" + "k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime/schema" "k8s.io/kubernetes/pkg/storage" @@ -954,3 +956,110 @@ func (e *Store) Export(ctx api.Context, name string, opts metav1.ExportOptions) } return obj, nil } + +// CompleteWithOptions updates the store with the provided options and defaults common fields +func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error { + if e.QualifiedResource.Empty() { + return fmt.Errorf("store %#v must have a non-empty qualified resource", e) + } + if e.NewFunc == nil { + return fmt.Errorf("store for %s must have NewFunc set", e.QualifiedResource.String()) + } + if e.NewListFunc == nil { + return fmt.Errorf("store for %s must have NewListFunc set", e.QualifiedResource.String()) + } + if (e.KeyRootFunc == nil) != (e.KeyFunc == nil) { + return fmt.Errorf("store for %s must set both KeyRootFunc and KeyFunc or neither", e.QualifiedResource.String()) + } + + var isNamespaced bool + switch { + case e.CreateStrategy != nil: + isNamespaced = e.CreateStrategy.NamespaceScoped() + case e.UpdateStrategy != nil: + isNamespaced = e.UpdateStrategy.NamespaceScoped() + default: + return fmt.Errorf("store for %s must have CreateStrategy or UpdateStrategy set", e.QualifiedResource.String()) + } + + if options.RESTOptions == nil { + return fmt.Errorf("options for %s must have RESTOptions set", e.QualifiedResource.String()) + } + if options.AttrFunc == nil { + return fmt.Errorf("options for %s must have AttrFunc set", e.QualifiedResource.String()) + } + + opts, err := options.RESTOptions.GetRESTOptions(e.QualifiedResource) + if err != nil { + return err + } + + // Resource prefix must come from the underlying factory + prefix := opts.ResourcePrefix + if !strings.HasPrefix(prefix, "/") { + prefix = "/" + prefix + } + if prefix == "/" { + return fmt.Errorf("store for %s has an invalid prefix %q", e.QualifiedResource.String(), opts.ResourcePrefix) + } + + // Set the default behavior for storage key generation + if e.KeyRootFunc == nil && e.KeyFunc == nil { + if isNamespaced { + e.KeyRootFunc = func(ctx api.Context) string { + return NamespaceKeyRootFunc(ctx, prefix) + } + e.KeyFunc = func(ctx api.Context, name string) (string, error) { + return NamespaceKeyFunc(ctx, prefix, name) + } + } else { + e.KeyRootFunc = func(ctx api.Context) string { + return prefix + } + e.KeyFunc = func(ctx api.Context, name string) (string, error) { + return NoNamespaceKeyFunc(ctx, prefix, name) + } + } + } + + // We adapt the store's keyFunc so that we can use it with the StorageDecorator + // without making any assumptions about where objects are stored in etcd + keyFunc := func(obj runtime.Object) (string, error) { + accessor, err := meta.Accessor(obj) + if err != nil { + return "", err + } + + if isNamespaced { + return e.KeyFunc(api.WithNamespace(api.NewContext(), accessor.GetNamespace()), accessor.GetName()) + } + + return e.KeyFunc(api.NewContext(), accessor.GetName()) + } + + triggerFunc := options.TriggerFunc + if triggerFunc == nil { + triggerFunc = storage.NoTriggerPublisher + } + + if e.DeleteCollectionWorkers == 0 { + e.DeleteCollectionWorkers = opts.DeleteCollectionWorkers + } + + e.EnableGarbageCollection = opts.EnableGarbageCollection + + if e.Storage == nil { + e.Storage, e.DestroyFunc = opts.Decorator( + opts.StorageConfig, + cachesize.GetWatchCacheSizeByResource(cachesize.Resource(e.QualifiedResource.Resource)), + e.NewFunc(), + prefix, + keyFunc, + e.NewListFunc, + options.AttrFunc, + triggerFunc, + ) + } + + return nil +} diff --git a/pkg/registry/generic/storage_decorator.go b/pkg/registry/generic/storage_decorator.go index 98f45f0b88..d74be6f82d 100644 --- a/pkg/registry/generic/storage_decorator.go +++ b/pkg/registry/generic/storage_decorator.go @@ -18,9 +18,6 @@ package generic import ( "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api/rest" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/storage" "k8s.io/kubernetes/pkg/storage/storagebackend" @@ -34,9 +31,9 @@ type StorageDecorator func( capacity int, objectType runtime.Object, resourcePrefix string, - scopeStrategy rest.NamespaceScopedStrategy, + keyFunc func(obj runtime.Object) (string, error), newListFunc func() runtime.Object, - getAttrsFunc func(runtime.Object) (labels.Set, fields.Set, error), + getAttrsFunc storage.AttrFunc, trigger storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc) // Returns given 'storageInterface' without any decoration. @@ -45,9 +42,9 @@ func UndecoratedStorage( capacity int, objectType runtime.Object, resourcePrefix string, - scopeStrategy rest.NamespaceScopedStrategy, + keyFunc func(obj runtime.Object) (string, error), newListFunc func() runtime.Object, - getAttrsFunc func(runtime.Object) (labels.Set, fields.Set, error), + getAttrsFunc storage.AttrFunc, trigger storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc) { return NewRawStorage(config) } diff --git a/pkg/registry/interfaces.go b/pkg/registry/interfaces.go deleted file mode 100644 index 7f8eea357f..0000000000 --- a/pkg/registry/interfaces.go +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright 2016 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 registry - -import ( - "k8s.io/kubernetes/pkg/registry/generic" - "k8s.io/kubernetes/pkg/runtime/schema" -) - -// RESTOptionsGetter is a function type for returning RESTOptions for a GroupVersion. -type RESTOptionsGetter func(resource schema.GroupResource) generic.RESTOptions diff --git a/pkg/registry/policy/poddisruptionbudget/etcd/BUILD b/pkg/registry/policy/poddisruptionbudget/etcd/BUILD index 10899a35dd..e539bd202f 100644 --- a/pkg/registry/policy/poddisruptionbudget/etcd/BUILD +++ b/pkg/registry/policy/poddisruptionbudget/etcd/BUILD @@ -19,12 +19,10 @@ go_library( "//pkg/api/rest:go_default_library", "//pkg/apis/meta/v1:go_default_library", "//pkg/apis/policy:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/registry/policy/poddisruptionbudget:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/policy/poddisruptionbudget/etcd/etcd.go b/pkg/registry/policy/poddisruptionbudget/etcd/etcd.go index 63ea31a334..14f19a0a59 100644 --- a/pkg/registry/policy/poddisruptionbudget/etcd/etcd.go +++ b/pkg/registry/policy/poddisruptionbudget/etcd/etcd.go @@ -21,12 +21,10 @@ import ( "k8s.io/kubernetes/pkg/api/rest" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" policyapi "k8s.io/kubernetes/pkg/apis/policy" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // rest implements a RESTStorage for pod disruption budgets against etcd @@ -35,56 +33,25 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against pod disruption budgets. -func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &policyapi.PodDisruptionBudgetList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.PodDisruptionBudget), - &policyapi.PodDisruptionBudget{}, - prefix, - poddisruptionbudget.Strategy, - newListFunc, - poddisruptionbudget.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &policyapi.PodDisruptionBudget{} }, - - // NewListFunc returns an object capable of storing results of an etcd list. - NewListFunc: newListFunc, - // Produces a podDisruptionBudget that etcd understands, to the root of the resource - // by combining the namespace in the context with the given prefix - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - // Produces a podDisruptionBudget that etcd understands, to the resource by combining - // the namespace in the context with the given prefix - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, name) - }, - // Retrieve the name field of a pod disruption budget + NewFunc: func() runtime.Object { return &policyapi.PodDisruptionBudget{} }, + NewListFunc: func() runtime.Object { return &policyapi.PodDisruptionBudgetList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*policyapi.PodDisruptionBudget).Name, nil }, - // Used to match objects based on labels/fields for list and watch - PredicateFunc: poddisruptionbudget.MatchPodDisruptionBudget, - QualifiedResource: policyapi.Resource("poddisruptionbudgets"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: poddisruptionbudget.MatchPodDisruptionBudget, + QualifiedResource: policyapi.Resource("poddisruptionbudgets"), - // Used to validate controller creation CreateStrategy: poddisruptionbudget.Strategy, - - // Used to validate controller updates UpdateStrategy: poddisruptionbudget.Strategy, DeleteStrategy: poddisruptionbudget.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: poddisruptionbudget.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up + } + statusStore := *store statusStore.UpdateStrategy = poddisruptionbudget.StatusStrategy return &REST{store}, &StatusREST{store: &statusStore} diff --git a/pkg/registry/policy/rest/BUILD b/pkg/registry/policy/rest/BUILD index 875fc50dae..09262067c5 100644 --- a/pkg/registry/policy/rest/BUILD +++ b/pkg/registry/policy/rest/BUILD @@ -19,7 +19,7 @@ go_library( "//pkg/apis/policy:go_default_library", "//pkg/apis/policy/v1beta1:go_default_library", "//pkg/genericapiserver:go_default_library", - "//pkg/registry:go_default_library", + "//pkg/registry/generic:go_default_library", "//pkg/registry/policy/poddisruptionbudget/etcd:go_default_library", ], ) diff --git a/pkg/registry/policy/rest/storage_policy.go b/pkg/registry/policy/rest/storage_policy.go index 777774bc8a..c175838868 100644 --- a/pkg/registry/policy/rest/storage_policy.go +++ b/pkg/registry/policy/rest/storage_policy.go @@ -21,13 +21,13 @@ import ( "k8s.io/kubernetes/pkg/apis/policy" policyapiv1beta1 "k8s.io/kubernetes/pkg/apis/policy/v1beta1" "k8s.io/kubernetes/pkg/genericapiserver" - "k8s.io/kubernetes/pkg/registry" + "k8s.io/kubernetes/pkg/registry/generic" poddisruptionbudgetetcd "k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/etcd" ) type RESTStorageProvider struct{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(policy.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(policyapiv1beta1.SchemeGroupVersion) { @@ -37,11 +37,11 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapise return apiGroupInfo, true } -func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { version := policyapiv1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} if apiResourceConfigSource.ResourceEnabled(version.WithResource("poddisruptionbudgets")) { - poddisruptionbudgetStorage, poddisruptionbudgetStatusStorage := poddisruptionbudgetetcd.NewREST(restOptionsGetter(policy.Resource("poddisruptionbudgets"))) + poddisruptionbudgetStorage, poddisruptionbudgetStatusStorage := poddisruptionbudgetetcd.NewREST(restOptionsGetter) storage["poddisruptionbudgets"] = poddisruptionbudgetStorage storage["poddisruptionbudgets/status"] = poddisruptionbudgetStatusStorage } diff --git a/pkg/registry/rbac/clusterrole/etcd/BUILD b/pkg/registry/rbac/clusterrole/etcd/BUILD index 21c2aeeb37..7c20e1370c 100644 --- a/pkg/registry/rbac/clusterrole/etcd/BUILD +++ b/pkg/registry/rbac/clusterrole/etcd/BUILD @@ -15,13 +15,10 @@ go_library( srcs = ["etcd.go"], tags = ["automanaged"], deps = [ - "//pkg/api:go_default_library", "//pkg/apis/rbac:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/registry/rbac/clusterrole:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/rbac/clusterrole/etcd/etcd.go b/pkg/registry/rbac/clusterrole/etcd/etcd.go index 3319b0234d..a6543f059d 100644 --- a/pkg/registry/rbac/clusterrole/etcd/etcd.go +++ b/pkg/registry/rbac/clusterrole/etcd/etcd.go @@ -17,14 +17,11 @@ limitations under the License. package etcd import ( - "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/rbac" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/registry/rbac/clusterrole" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // REST implements a RESTStorage for ClusterRole against etcd @@ -33,44 +30,23 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against ClusterRole objects. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &rbac.ClusterRoleList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.ClusterRoles), - &rbac.ClusterRole{}, - prefix, - clusterrole.Strategy, - newListFunc, - clusterrole.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &rbac.ClusterRole{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, id string) (string, error) { - return genericregistry.NoNamespaceKeyFunc(ctx, prefix, id) - }, + NewListFunc: func() runtime.Object { return &rbac.ClusterRoleList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*rbac.ClusterRole).Name, nil }, - PredicateFunc: clusterrole.Matcher, - QualifiedResource: rbac.Resource("clusterroles"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: clusterrole.Matcher, + QualifiedResource: rbac.Resource("clusterroles"), CreateStrategy: clusterrole.Strategy, UpdateStrategy: clusterrole.Strategy, DeleteStrategy: clusterrole.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: clusterrole.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} diff --git a/pkg/registry/rbac/clusterrolebinding/etcd/BUILD b/pkg/registry/rbac/clusterrolebinding/etcd/BUILD index dbd5dacb73..625903dc27 100644 --- a/pkg/registry/rbac/clusterrolebinding/etcd/BUILD +++ b/pkg/registry/rbac/clusterrolebinding/etcd/BUILD @@ -15,13 +15,10 @@ go_library( srcs = ["etcd.go"], tags = ["automanaged"], deps = [ - "//pkg/api:go_default_library", "//pkg/apis/rbac:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/registry/rbac/clusterrolebinding:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/rbac/clusterrolebinding/etcd/etcd.go b/pkg/registry/rbac/clusterrolebinding/etcd/etcd.go index a28fd0b155..8a723835d3 100644 --- a/pkg/registry/rbac/clusterrolebinding/etcd/etcd.go +++ b/pkg/registry/rbac/clusterrolebinding/etcd/etcd.go @@ -17,14 +17,11 @@ limitations under the License. package etcd import ( - "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/rbac" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // REST implements a RESTStorage for ClusterRoleBinding against etcd @@ -33,44 +30,23 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against ClusterRoleBinding objects. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &rbac.ClusterRoleBindingList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.ClusterRoleBindings), - &rbac.ClusterRoleBinding{}, - prefix, - clusterrolebinding.Strategy, - newListFunc, - clusterrolebinding.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &rbac.ClusterRoleBinding{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, id string) (string, error) { - return genericregistry.NoNamespaceKeyFunc(ctx, prefix, id) - }, + NewListFunc: func() runtime.Object { return &rbac.ClusterRoleBindingList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*rbac.ClusterRoleBinding).Name, nil }, - PredicateFunc: clusterrolebinding.Matcher, - QualifiedResource: rbac.Resource("clusterrolebindings"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: clusterrolebinding.Matcher, + QualifiedResource: rbac.Resource("clusterrolebindings"), CreateStrategy: clusterrolebinding.Strategy, UpdateStrategy: clusterrolebinding.Strategy, DeleteStrategy: clusterrolebinding.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: clusterrolebinding.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} diff --git a/pkg/registry/rbac/rest/BUILD b/pkg/registry/rbac/rest/BUILD index 0872818782..7da80dad83 100644 --- a/pkg/registry/rbac/rest/BUILD +++ b/pkg/registry/rbac/rest/BUILD @@ -22,7 +22,7 @@ go_library( "//pkg/apis/rbac/validation:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library", "//pkg/genericapiserver:go_default_library", - "//pkg/registry:go_default_library", + "//pkg/registry/generic:go_default_library", "//pkg/registry/rbac/clusterrole:go_default_library", "//pkg/registry/rbac/clusterrole/etcd:go_default_library", "//pkg/registry/rbac/clusterrole/policybased:go_default_library", diff --git a/pkg/registry/rbac/rest/storage_rbac.go b/pkg/registry/rbac/rest/storage_rbac.go index 898f0aa262..0ab6b7a57e 100644 --- a/pkg/registry/rbac/rest/storage_rbac.go +++ b/pkg/registry/rbac/rest/storage_rbac.go @@ -29,7 +29,7 @@ import ( rbacvalidation "k8s.io/kubernetes/pkg/apis/rbac/validation" rbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" "k8s.io/kubernetes/pkg/genericapiserver" - "k8s.io/kubernetes/pkg/registry" + "k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/rbac/clusterrole" clusterroleetcd "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/etcd" clusterrolepolicybased "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased" @@ -50,7 +50,7 @@ type RESTStorageProvider struct{} var _ genericapiserver.PostStartHookProvider = RESTStorageProvider{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(rbac.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(rbacapiv1alpha1.SchemeGroupVersion) { @@ -61,39 +61,50 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapise return apiGroupInfo, true } -func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { version := rbacapiv1alpha1.SchemeGroupVersion once := new(sync.Once) - var authorizationRuleResolver rbacvalidation.AuthorizationRuleResolver - newRuleValidator := func() rbacvalidation.AuthorizationRuleResolver { + var ( + authorizationRuleResolver rbacvalidation.AuthorizationRuleResolver + rolesStorage rest.StandardStorage + roleBindingsStorage rest.StandardStorage + clusterRolesStorage rest.StandardStorage + clusterRoleBindingsStorage rest.StandardStorage + ) + + initializeStorage := func() { once.Do(func() { + rolesStorage = roleetcd.NewREST(restOptionsGetter) + roleBindingsStorage = rolebindingetcd.NewREST(restOptionsGetter) + clusterRolesStorage = clusterroleetcd.NewREST(restOptionsGetter) + clusterRoleBindingsStorage = clusterrolebindingetcd.NewREST(restOptionsGetter) + authorizationRuleResolver = rbacvalidation.NewDefaultRuleResolver( - role.AuthorizerAdapter{Registry: role.NewRegistry(roleetcd.NewREST(restOptionsGetter(rbac.Resource("roles"))))}, - rolebinding.AuthorizerAdapter{Registry: rolebinding.NewRegistry(rolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("rolebindings"))))}, - clusterrole.AuthorizerAdapter{Registry: clusterrole.NewRegistry(clusterroleetcd.NewREST(restOptionsGetter(rbac.Resource("clusterroles"))))}, - clusterrolebinding.AuthorizerAdapter{Registry: clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("clusterrolebindings"))))}, + role.AuthorizerAdapter{Registry: role.NewRegistry(rolesStorage)}, + rolebinding.AuthorizerAdapter{Registry: rolebinding.NewRegistry(roleBindingsStorage)}, + clusterrole.AuthorizerAdapter{Registry: clusterrole.NewRegistry(clusterRolesStorage)}, + clusterrolebinding.AuthorizerAdapter{Registry: clusterrolebinding.NewRegistry(clusterRoleBindingsStorage)}, ) }) - return authorizationRuleResolver } storage := map[string]rest.Storage{} if apiResourceConfigSource.ResourceEnabled(version.WithResource("roles")) { - rolesStorage := roleetcd.NewREST(restOptionsGetter(rbac.Resource("roles"))) - storage["roles"] = rolepolicybased.NewStorage(rolesStorage, newRuleValidator()) + initializeStorage() + storage["roles"] = rolepolicybased.NewStorage(rolesStorage, authorizationRuleResolver) } if apiResourceConfigSource.ResourceEnabled(version.WithResource("rolebindings")) { - roleBindingsStorage := rolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("rolebindings"))) - storage["rolebindings"] = rolebindingpolicybased.NewStorage(roleBindingsStorage, newRuleValidator()) + initializeStorage() + storage["rolebindings"] = rolebindingpolicybased.NewStorage(roleBindingsStorage, authorizationRuleResolver) } if apiResourceConfigSource.ResourceEnabled(version.WithResource("clusterroles")) { - clusterRolesStorage := clusterroleetcd.NewREST(restOptionsGetter(rbac.Resource("clusterroles"))) - storage["clusterroles"] = clusterrolepolicybased.NewStorage(clusterRolesStorage, newRuleValidator()) + initializeStorage() + storage["clusterroles"] = clusterrolepolicybased.NewStorage(clusterRolesStorage, authorizationRuleResolver) } if apiResourceConfigSource.ResourceEnabled(version.WithResource("clusterrolebindings")) { - clusterRoleBindingsStorage := clusterrolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("clusterrolebindings"))) - storage["clusterrolebindings"] = clusterrolebindingpolicybased.NewStorage(clusterRoleBindingsStorage, newRuleValidator()) + initializeStorage() + storage["clusterrolebindings"] = clusterrolebindingpolicybased.NewStorage(clusterRoleBindingsStorage, authorizationRuleResolver) } return storage } diff --git a/pkg/registry/rbac/role/etcd/BUILD b/pkg/registry/rbac/role/etcd/BUILD index c891e14d96..444d8c8a2c 100644 --- a/pkg/registry/rbac/role/etcd/BUILD +++ b/pkg/registry/rbac/role/etcd/BUILD @@ -15,13 +15,10 @@ go_library( srcs = ["etcd.go"], tags = ["automanaged"], deps = [ - "//pkg/api:go_default_library", "//pkg/apis/rbac:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/registry/rbac/role:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/rbac/role/etcd/etcd.go b/pkg/registry/rbac/role/etcd/etcd.go index e5a8f491f5..8a441884f1 100644 --- a/pkg/registry/rbac/role/etcd/etcd.go +++ b/pkg/registry/rbac/role/etcd/etcd.go @@ -17,14 +17,11 @@ limitations under the License. package etcd import ( - "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/rbac" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/registry/rbac/role" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // REST implements a RESTStorage for Role against etcd @@ -33,44 +30,23 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against Role objects. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &rbac.RoleList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.Roles), - &rbac.Role{}, - prefix, - role.Strategy, - newListFunc, - role.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &rbac.Role{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, id string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, id) - }, + NewListFunc: func() runtime.Object { return &rbac.RoleList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*rbac.Role).Name, nil }, - PredicateFunc: role.Matcher, - QualifiedResource: rbac.Resource("roles"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: role.Matcher, + QualifiedResource: rbac.Resource("roles"), CreateStrategy: role.Strategy, UpdateStrategy: role.Strategy, DeleteStrategy: role.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: role.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} diff --git a/pkg/registry/rbac/rolebinding/etcd/BUILD b/pkg/registry/rbac/rolebinding/etcd/BUILD index 6b18425980..d331005925 100644 --- a/pkg/registry/rbac/rolebinding/etcd/BUILD +++ b/pkg/registry/rbac/rolebinding/etcd/BUILD @@ -15,13 +15,10 @@ go_library( srcs = ["etcd.go"], tags = ["automanaged"], deps = [ - "//pkg/api:go_default_library", "//pkg/apis/rbac:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/registry/rbac/rolebinding:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/rbac/rolebinding/etcd/etcd.go b/pkg/registry/rbac/rolebinding/etcd/etcd.go index f6ad32f4e0..0949579378 100644 --- a/pkg/registry/rbac/rolebinding/etcd/etcd.go +++ b/pkg/registry/rbac/rolebinding/etcd/etcd.go @@ -17,14 +17,11 @@ limitations under the License. package etcd import ( - "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/rbac" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/registry/rbac/rolebinding" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) // REST implements a RESTStorage for RoleBinding against etcd @@ -33,44 +30,23 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against RoleBinding objects. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &rbac.RoleBindingList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.RoleBindings), - &rbac.RoleBinding{}, - prefix, - rolebinding.Strategy, - newListFunc, - rolebinding.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &rbac.RoleBinding{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return genericregistry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, id string) (string, error) { - return genericregistry.NamespaceKeyFunc(ctx, prefix, id) - }, + NewListFunc: func() runtime.Object { return &rbac.RoleBindingList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*rbac.RoleBinding).Name, nil }, - PredicateFunc: rolebinding.Matcher, - QualifiedResource: rbac.Resource("rolebindings"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: rolebinding.Matcher, + QualifiedResource: rbac.Resource("rolebindings"), CreateStrategy: rolebinding.Strategy, UpdateStrategy: rolebinding.Strategy, DeleteStrategy: rolebinding.Strategy, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: rolebinding.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} diff --git a/pkg/registry/storage/rest/BUILD b/pkg/registry/storage/rest/BUILD index cc787f85fd..7d108a4ef7 100644 --- a/pkg/registry/storage/rest/BUILD +++ b/pkg/registry/storage/rest/BUILD @@ -19,7 +19,7 @@ go_library( "//pkg/apis/storage:go_default_library", "//pkg/apis/storage/v1beta1:go_default_library", "//pkg/genericapiserver:go_default_library", - "//pkg/registry:go_default_library", + "//pkg/registry/generic:go_default_library", "//pkg/registry/storage/storageclass/etcd:go_default_library", ], ) diff --git a/pkg/registry/storage/rest/storage_storage.go b/pkg/registry/storage/rest/storage_storage.go index 9e095b448b..defc8cfce1 100644 --- a/pkg/registry/storage/rest/storage_storage.go +++ b/pkg/registry/storage/rest/storage_storage.go @@ -21,14 +21,14 @@ import ( storageapi "k8s.io/kubernetes/pkg/apis/storage" storageapiv1beta1 "k8s.io/kubernetes/pkg/apis/storage/v1beta1" "k8s.io/kubernetes/pkg/genericapiserver" - "k8s.io/kubernetes/pkg/registry" + "k8s.io/kubernetes/pkg/registry/generic" storageclassetcd "k8s.io/kubernetes/pkg/registry/storage/storageclass/etcd" ) type RESTStorageProvider struct { } -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(storageapi.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(storageapiv1beta1.SchemeGroupVersion) { @@ -39,13 +39,13 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapise return apiGroupInfo, true } -func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter registry.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { version := storageapiv1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} if apiResourceConfigSource.ResourceEnabled(version.WithResource("storageclasses")) { - storageClassStorage := storageclassetcd.NewREST(restOptionsGetter(storageapi.Resource("storageclasses"))) + storageClassStorage := storageclassetcd.NewREST(restOptionsGetter) storage["storageclasses"] = storageClassStorage } diff --git a/pkg/registry/storage/storageclass/etcd/BUILD b/pkg/registry/storage/storageclass/etcd/BUILD index ea77c18d3e..f59fcb53d5 100644 --- a/pkg/registry/storage/storageclass/etcd/BUILD +++ b/pkg/registry/storage/storageclass/etcd/BUILD @@ -15,14 +15,11 @@ go_library( srcs = ["etcd.go"], tags = ["automanaged"], deps = [ - "//pkg/api:go_default_library", "//pkg/apis/storage:go_default_library", - "//pkg/registry/cachesize:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/registry/generic/registry:go_default_library", "//pkg/registry/storage/storageclass:go_default_library", "//pkg/runtime:go_default_library", - "//pkg/storage:go_default_library", ], ) diff --git a/pkg/registry/storage/storageclass/etcd/etcd.go b/pkg/registry/storage/storageclass/etcd/etcd.go index a9a5df7e24..26ccf7450f 100644 --- a/pkg/registry/storage/storageclass/etcd/etcd.go +++ b/pkg/registry/storage/storageclass/etcd/etcd.go @@ -17,14 +17,11 @@ limitations under the License. package etcd import ( - "k8s.io/kubernetes/pkg/api" storageapi "k8s.io/kubernetes/pkg/apis/storage" - "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/generic" genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/registry/storage/storageclass" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" ) type REST struct { @@ -32,45 +29,24 @@ type REST struct { } // NewREST returns a RESTStorage object that will work against persistent volumes. -func NewREST(opts generic.RESTOptions) *REST { - prefix := "/" + opts.ResourcePrefix - - newListFunc := func() runtime.Object { return &storageapi.StorageClassList{} } - storageInterface, dFunc := opts.Decorator( - opts.StorageConfig, - cachesize.GetWatchCacheSizeByResource(cachesize.StorageClasses), - &storageapi.StorageClass{}, - prefix, - storageclass.Strategy, - newListFunc, - storageclass.GetAttrs, - storage.NoTriggerPublisher, - ) - +func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &storageapi.StorageClass{} }, - NewListFunc: newListFunc, - KeyRootFunc: func(ctx api.Context) string { - return prefix - }, - KeyFunc: func(ctx api.Context, name string) (string, error) { - return genericregistry.NoNamespaceKeyFunc(ctx, prefix, name) - }, + NewListFunc: func() runtime.Object { return &storageapi.StorageClassList{} }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*storageapi.StorageClass).Name, nil }, - PredicateFunc: storageclass.MatchStorageClasses, - QualifiedResource: storageapi.Resource("storageclasses"), - EnableGarbageCollection: opts.EnableGarbageCollection, - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, + PredicateFunc: storageclass.MatchStorageClasses, + QualifiedResource: storageapi.Resource("storageclasses"), CreateStrategy: storageclass.Strategy, UpdateStrategy: storageclass.Strategy, DeleteStrategy: storageclass.Strategy, ReturnDeletedObject: true, - - Storage: storageInterface, - DestroyFunc: dFunc, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: storageclass.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + panic(err) // TODO: Propagate error up } return &REST{store} diff --git a/pkg/registry/storage/storageclass/etcd/etcd_test.go b/pkg/registry/storage/storageclass/etcd/etcd_test.go index 09cc3c200d..e84d9b2813 100644 --- a/pkg/registry/storage/storageclass/etcd/etcd_test.go +++ b/pkg/registry/storage/storageclass/etcd/etcd_test.go @@ -31,7 +31,12 @@ import ( func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, storageapi.GroupName) - restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "storageclasses", + } storageClassStorage := NewREST(restOptions) return storageClassStorage, server } diff --git a/test/integration/auth/rbac_test.go b/test/integration/auth/rbac_test.go index 91e49fc290..78dddcdf40 100644 --- a/test/integration/auth/rbac_test.go +++ b/test/integration/auth/rbac_test.go @@ -50,6 +50,7 @@ import ( roleetcd "k8s.io/kubernetes/pkg/registry/rbac/role/etcd" "k8s.io/kubernetes/pkg/registry/rbac/rolebinding" rolebindingetcd "k8s.io/kubernetes/pkg/registry/rbac/rolebinding/etcd" + "k8s.io/kubernetes/pkg/runtime/schema" "k8s.io/kubernetes/pkg/watch" "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/anytoken" "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac" @@ -75,19 +76,24 @@ func clientsetForUser(user string, config *restclient.Config) clientset.Interfac return clientset.NewForConfigOrDie(&configCopy) } -func newRBACAuthorizer(t *testing.T, config *master.Config) authorizer.Authorizer { - newRESTOptions := func(resource string) generic.RESTOptions { - storageConfig, err := config.StorageFactory.NewConfig(rbacapi.Resource(resource)) - if err != nil { - t.Fatalf("failed to get storage: %v", err) - } - return generic.RESTOptions{StorageConfig: storageConfig, Decorator: generic.UndecoratedStorage, ResourcePrefix: resource} - } +type testRESTOptionsGetter struct { + config *master.Config +} - roleRegistry := role.AuthorizerAdapter{Registry: role.NewRegistry(roleetcd.NewREST(newRESTOptions("roles")))} - roleBindingRegistry := rolebinding.AuthorizerAdapter{Registry: rolebinding.NewRegistry(rolebindingetcd.NewREST(newRESTOptions("rolebindings")))} - clusterRoleRegistry := clusterrole.AuthorizerAdapter{Registry: clusterrole.NewRegistry(clusterroleetcd.NewREST(newRESTOptions("clusterroles")))} - clusterRoleBindingRegistry := clusterrolebinding.AuthorizerAdapter{Registry: clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(newRESTOptions("clusterrolebindings")))} +func (getter *testRESTOptionsGetter) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) { + storageConfig, err := getter.config.StorageFactory.NewConfig(resource) + if err != nil { + return generic.RESTOptions{}, fmt.Errorf("failed to get storage: %v", err) + } + return generic.RESTOptions{StorageConfig: storageConfig, Decorator: generic.UndecoratedStorage, ResourcePrefix: resource.Resource}, nil +} + +func newRBACAuthorizer(config *master.Config) authorizer.Authorizer { + optsGetter := &testRESTOptionsGetter{config} + roleRegistry := role.AuthorizerAdapter{Registry: role.NewRegistry(roleetcd.NewREST(optsGetter))} + roleBindingRegistry := rolebinding.AuthorizerAdapter{Registry: rolebinding.NewRegistry(rolebindingetcd.NewREST(optsGetter))} + clusterRoleRegistry := clusterrole.AuthorizerAdapter{Registry: clusterrole.NewRegistry(clusterroleetcd.NewREST(optsGetter))} + clusterRoleBindingRegistry := clusterrolebinding.AuthorizerAdapter{Registry: clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(optsGetter))} return rbac.New(roleRegistry, roleBindingRegistry, clusterRoleRegistry, clusterRoleBindingRegistry) } @@ -332,7 +338,7 @@ func TestRBAC(t *testing.T) { for i, tc := range tests { // Create an API Server. masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authorizer = newRBACAuthorizer(t, masterConfig) + masterConfig.GenericConfig.Authorizer = newRBACAuthorizer(masterConfig) masterConfig.GenericConfig.Authenticator = newFakeAuthenticator() _, s := framework.RunAMaster(masterConfig) defer s.Close() @@ -430,7 +436,7 @@ func TestBootstrapping(t *testing.T) { superUser := "admin/system:masters" masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authorizer = newRBACAuthorizer(t, masterConfig) + masterConfig.GenericConfig.Authorizer = newRBACAuthorizer(masterConfig) masterConfig.GenericConfig.Authenticator = newFakeAuthenticator() _, s := framework.RunAMaster(masterConfig) defer s.Close()