From 57604816c75ce233609a2b1c67e55c0addb27f4f Mon Sep 17 00:00:00 2001 From: Monis Khan Date: Wed, 30 Nov 2016 21:09:56 -0500 Subject: [PATCH] Refactor REST storage to use generic defaults Signed-off-by: Monis Khan --- apiserver/apiserver.go | 9 +++- apiserver/rest/reststorage.go | 79 ++++++++++++++++------------------- apiserver/server/main.go | 2 +- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/apiserver/apiserver.go b/apiserver/apiserver.go index 5442a6f1..ddfdec5e 100644 --- a/apiserver/apiserver.go +++ b/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/apiserver/rest/reststorage.go b/apiserver/rest/reststorage.go index 3d8ced15..00e27429 100644 --- a/apiserver/rest/reststorage.go +++ b/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/apiserver/server/main.go b/apiserver/server/main.go index 5dff0131..6dd94f30 100644 --- a/apiserver/server/main.go +++ b/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)