Refactor REST storage to use generic defaults
Signed-off-by: Monis Khan <mkhan@redhat.com>
This commit is contained in:
parent
dd974b7412
commit
57604816c7
|
@ -128,8 +128,15 @@ func (serverOptions *ServerRunOptions) Run(stopCh <-chan struct{}) error {
|
||||||
return fmt.Errorf("Unable to get storage config: %v", err)
|
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{
|
restStorageMap := map[string]rest.Storage{
|
||||||
"testtypes": testgroupetcd.NewREST(storageConfig, generic.UndecoratedStorage),
|
"testtypes": testgroupetcd.NewREST(testTypeOpts),
|
||||||
}
|
}
|
||||||
apiGroupInfo := genericapiserver.APIGroupInfo{
|
apiGroupInfo := genericapiserver.APIGroupInfo{
|
||||||
GroupMeta: *groupMeta,
|
GroupMeta: *groupMeta,
|
||||||
|
|
|
@ -27,7 +27,7 @@ import (
|
||||||
genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry"
|
genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
"k8s.io/kubernetes/pkg/storage"
|
"k8s.io/kubernetes/pkg/storage"
|
||||||
"k8s.io/kubernetes/pkg/storage/storagebackend"
|
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||||
)
|
)
|
||||||
|
|
||||||
type REST struct {
|
type REST struct {
|
||||||
|
@ -35,60 +35,53 @@ type REST struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewREST returns a RESTStorage object that will work with testtype.
|
// NewREST returns a RESTStorage object that will work with testtype.
|
||||||
func NewREST(config *storagebackend.Config, storageDecorator generic.StorageDecorator) *REST {
|
func NewREST(optsGetter generic.RESTOptionsGetter) *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)
|
|
||||||
store := &genericregistry.Store{
|
store := &genericregistry.Store{
|
||||||
NewFunc: func() runtime.Object { return &testgroup.TestType{} },
|
NewFunc: func() runtime.Object { return &testgroup.TestType{} },
|
||||||
// NewListFunc returns an object capable of storing results of an etcd list.
|
// NewListFunc returns an object capable of storing results of an etcd list.
|
||||||
NewListFunc: newListFunc,
|
NewListFunc: func() runtime.Object { return &testgroup.TestTypeList{} },
|
||||||
// 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 the resource.
|
// Retrieve the name field of the resource.
|
||||||
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
||||||
return obj.(*testgroup.TestType).Name, nil
|
return obj.(*testgroup.TestType).Name, nil
|
||||||
},
|
},
|
||||||
// Used to match objects based on labels/fields for list.
|
// Used to match objects based on labels/fields for list.
|
||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
PredicateFunc: matcher,
|
||||||
return storage.SelectionPredicate{
|
// QualifiedResource should always be plural
|
||||||
Label: label,
|
QualifiedResource: api.Resource("testtypes"),
|
||||||
Field: field,
|
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
CreateStrategy: strategy,
|
||||||
testType, ok := obj.(*testgroup.TestType)
|
}
|
||||||
if !ok {
|
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: getAttrs}
|
||||||
return nil, nil, fmt.Errorf("unexpected type of given object")
|
if err := store.CompleteWithOptions(options); err != nil {
|
||||||
}
|
panic(err) // TODO: Propagate error up
|
||||||
return labels.Set(testType.ObjectMeta.Labels), fields.Set{}, nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Storage: storageInterface,
|
|
||||||
}
|
}
|
||||||
return &REST{store}
|
return &REST{store}
|
||||||
}
|
}
|
||||||
|
|
||||||
type NotNamespaceScoped struct {
|
type fakeStrategy struct {
|
||||||
|
runtime.ObjectTyper
|
||||||
|
api.NameGenerator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*NotNamespaceScoped) NamespaceScoped() bool {
|
func (*fakeStrategy) NamespaceScoped() bool { return false }
|
||||||
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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ func main() {
|
||||||
serverRunOptions := apiserver.NewServerRunOptions()
|
serverRunOptions := apiserver.NewServerRunOptions()
|
||||||
|
|
||||||
// Parse command line flags.
|
// Parse command line flags.
|
||||||
serverRunOptions.AddUniversalFlags(pflag.CommandLine)
|
serverRunOptions.GenericServerRunOptions.AddUniversalFlags(pflag.CommandLine)
|
||||||
serverRunOptions.Etcd.AddFlags(pflag.CommandLine)
|
serverRunOptions.Etcd.AddFlags(pflag.CommandLine)
|
||||||
serverRunOptions.SecureServing.AddFlags(pflag.CommandLine)
|
serverRunOptions.SecureServing.AddFlags(pflag.CommandLine)
|
||||||
serverRunOptions.SecureServing.AddDeprecatedFlags(pflag.CommandLine)
|
serverRunOptions.SecureServing.AddDeprecatedFlags(pflag.CommandLine)
|
||||||
|
|
Loading…
Reference in New Issue