Propagate error from NewREST

This commit is contained in:
Ted Yu
2019-08-12 13:55:33 -07:00
committed by Ted Yu
parent c981c65c90
commit 87b2a3129b
100 changed files with 917 additions and 408 deletions

View File

@@ -329,7 +329,9 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
ServiceAccountMaxExpiration: c.ExtraConfig.ServiceAccountMaxExpiration, ServiceAccountMaxExpiration: c.ExtraConfig.ServiceAccountMaxExpiration,
APIAudiences: c.GenericConfig.Authentication.APIAudiences, APIAudiences: c.GenericConfig.Authentication.APIAudiences,
} }
m.InstallLegacyAPI(&c, c.GenericConfig.RESTOptionsGetter, legacyRESTStorageProvider) if err := m.InstallLegacyAPI(&c, c.GenericConfig.RESTOptionsGetter, legacyRESTStorageProvider); err != nil {
return nil, err
}
} }
// The order here is preserved in discovery. // The order here is preserved in discovery.
@@ -361,7 +363,9 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
admissionregistrationrest.RESTStorageProvider{}, admissionregistrationrest.RESTStorageProvider{},
eventsrest.RESTStorageProvider{TTL: c.ExtraConfig.EventTTL}, eventsrest.RESTStorageProvider{TTL: c.ExtraConfig.EventTTL},
} }
m.InstallAPIs(c.ExtraConfig.APIResourceConfigSource, c.GenericConfig.RESTOptionsGetter, restStorageProviders...) if err := m.InstallAPIs(c.ExtraConfig.APIResourceConfigSource, c.GenericConfig.RESTOptionsGetter, restStorageProviders...); err != nil {
return nil, err
}
if c.ExtraConfig.Tunneler != nil { if c.ExtraConfig.Tunneler != nil {
m.installTunneler(c.ExtraConfig.Tunneler, corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig).Nodes()) m.installTunneler(c.ExtraConfig.Tunneler, corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig).Nodes())
@@ -372,10 +376,10 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
return m, nil return m, nil
} }
func (m *Master) InstallLegacyAPI(c *completedConfig, restOptionsGetter generic.RESTOptionsGetter, legacyRESTStorageProvider corerest.LegacyRESTStorageProvider) { func (m *Master) InstallLegacyAPI(c *completedConfig, restOptionsGetter generic.RESTOptionsGetter, legacyRESTStorageProvider corerest.LegacyRESTStorageProvider) error {
legacyRESTStorage, apiGroupInfo, err := legacyRESTStorageProvider.NewLegacyRESTStorage(restOptionsGetter) legacyRESTStorage, apiGroupInfo, err := legacyRESTStorageProvider.NewLegacyRESTStorage(restOptionsGetter)
if err != nil { if err != nil {
klog.Fatalf("Error building core storage: %v", err) return fmt.Errorf("Error building core storage: %v", err)
} }
controllerName := "bootstrap-controller" controllerName := "bootstrap-controller"
@@ -385,8 +389,9 @@ func (m *Master) InstallLegacyAPI(c *completedConfig, restOptionsGetter generic.
m.GenericAPIServer.AddPreShutdownHookOrDie(controllerName, bootstrapController.PreShutdownHook) m.GenericAPIServer.AddPreShutdownHookOrDie(controllerName, bootstrapController.PreShutdownHook)
if err := m.GenericAPIServer.InstallLegacyAPIGroup(genericapiserver.DefaultLegacyAPIPrefix, &apiGroupInfo); err != nil { if err := m.GenericAPIServer.InstallLegacyAPIGroup(genericapiserver.DefaultLegacyAPIPrefix, &apiGroupInfo); err != nil {
klog.Fatalf("Error in registering group versions: %v", err) return fmt.Errorf("Error in registering group versions: %v", err)
} }
return nil
} }
func (m *Master) installTunneler(nodeTunneler tunneler.Tunneler, nodeClient corev1client.NodeInterface) { func (m *Master) installTunneler(nodeTunneler tunneler.Tunneler, nodeClient corev1client.NodeInterface) {
@@ -405,11 +410,11 @@ func (m *Master) installTunneler(nodeTunneler tunneler.Tunneler, nodeClient core
// RESTStorageProvider is a factory type for REST storage. // RESTStorageProvider is a factory type for REST storage.
type RESTStorageProvider interface { type RESTStorageProvider interface {
GroupName() string GroupName() string
NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error)
} }
// InstallAPIs will install the APIs for the restStorageProviders if they are enabled. // InstallAPIs will install the APIs for the restStorageProviders if they are enabled.
func (m *Master) InstallAPIs(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter, restStorageProviders ...RESTStorageProvider) { func (m *Master) InstallAPIs(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter, restStorageProviders ...RESTStorageProvider) error {
apiGroupsInfo := []*genericapiserver.APIGroupInfo{} apiGroupsInfo := []*genericapiserver.APIGroupInfo{}
for _, restStorageBuilder := range restStorageProviders { for _, restStorageBuilder := range restStorageProviders {
@@ -418,9 +423,12 @@ func (m *Master) InstallAPIs(apiResourceConfigSource serverstorage.APIResourceCo
klog.V(1).Infof("Skipping disabled API group %q.", groupName) klog.V(1).Infof("Skipping disabled API group %q.", groupName)
continue continue
} }
apiGroupInfo, enabled := restStorageBuilder.NewRESTStorage(apiResourceConfigSource, restOptionsGetter) apiGroupInfo, enabled, err := restStorageBuilder.NewRESTStorage(apiResourceConfigSource, restOptionsGetter)
if err != nil {
return fmt.Errorf("problem initializing API group %q : %v.", groupName, err)
}
if !enabled { if !enabled {
klog.Warningf("Problem initializing API group %q, skipping.", groupName) klog.Warningf("API group %q is not enabled, skipping.", groupName)
continue continue
} }
klog.V(1).Infof("Enabling API group %q.", groupName) klog.V(1).Infof("Enabling API group %q.", groupName)
@@ -437,8 +445,9 @@ func (m *Master) InstallAPIs(apiResourceConfigSource serverstorage.APIResourceCo
} }
if err := m.GenericAPIServer.InstallAPIGroups(apiGroupsInfo...); err != nil { if err := m.GenericAPIServer.InstallAPIGroups(apiGroupsInfo...); err != nil {
klog.Fatalf("Error in registering group versions: %v", err) return fmt.Errorf("Error in registering group versions: %v", err)
} }
return nil
} }
type nodeAddressProvider struct { type nodeAddressProvider struct {

View File

@@ -182,7 +182,10 @@ func TestCertificatesRestStorageStrategies(t *testing.T) {
defer etcdserver.Terminate(t) defer etcdserver.Terminate(t)
certStorageProvider := certificatesrest.RESTStorageProvider{} certStorageProvider := certificatesrest.RESTStorageProvider{}
apiGroupInfo, _ := certStorageProvider.NewRESTStorage(masterCfg.ExtraConfig.APIResourceConfigSource, masterCfg.GenericConfig.RESTOptionsGetter) apiGroupInfo, _, err := certStorageProvider.NewRESTStorage(masterCfg.ExtraConfig.APIResourceConfigSource, masterCfg.GenericConfig.RESTOptionsGetter)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
exceptions := registrytest.StrategyExceptions{ exceptions := registrytest.StrategyExceptions{
HasExportStrategy: []string{ HasExportStrategy: []string{

View File

@@ -30,7 +30,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against pod disruption budgets. // NewREST returns a RESTStorage object that will work against pod disruption budgets.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &admissionregistration.MutatingWebhookConfiguration{} }, NewFunc: func() runtime.Object { return &admissionregistration.MutatingWebhookConfiguration{} },
NewListFunc: func() runtime.Object { return &admissionregistration.MutatingWebhookConfigurationList{} }, NewListFunc: func() runtime.Object { return &admissionregistration.MutatingWebhookConfigurationList{} },
@@ -45,7 +45,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -31,44 +31,64 @@ import (
type RESTStorageProvider struct{} type RESTStorageProvider struct{}
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(admissionregistration.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(admissionregistration.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(admissionregistrationv1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(admissionregistrationv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[admissionregistrationv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[admissionregistrationv1beta1.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(admissionregistrationv1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(admissionregistrationv1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[admissionregistrationv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[admissionregistrationv1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// validatingwebhookconfigurations // validatingwebhookconfigurations
validatingStorage := validatingwebhookconfigurationstorage.NewREST(restOptionsGetter) validatingStorage, err := validatingwebhookconfigurationstorage.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["validatingwebhookconfigurations"] = validatingStorage storage["validatingwebhookconfigurations"] = validatingStorage
// mutatingwebhookconfigurations // mutatingwebhookconfigurations
mutatingStorage := mutatingwebhookconfigurationstorage.NewREST(restOptionsGetter) mutatingStorage, err := mutatingwebhookconfigurationstorage.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["mutatingwebhookconfigurations"] = mutatingStorage storage["mutatingwebhookconfigurations"] = mutatingStorage
return storage return storage, err
} }
func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// validatingwebhookconfigurations // validatingwebhookconfigurations
validatingStorage := validatingwebhookconfigurationstorage.NewREST(restOptionsGetter) validatingStorage, err := validatingwebhookconfigurationstorage.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["validatingwebhookconfigurations"] = validatingStorage storage["validatingwebhookconfigurations"] = validatingStorage
// mutatingwebhookconfigurations // mutatingwebhookconfigurations
mutatingStorage := mutatingwebhookconfigurationstorage.NewREST(restOptionsGetter) mutatingStorage, err := mutatingwebhookconfigurationstorage.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["mutatingwebhookconfigurations"] = mutatingStorage storage["mutatingwebhookconfigurations"] = mutatingStorage
return storage return storage, err
} }
func (p RESTStorageProvider) GroupName() string { func (p RESTStorageProvider) GroupName() string {

View File

@@ -30,7 +30,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against pod disruption budgets. // NewREST returns a RESTStorage object that will work against pod disruption budgets.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &admissionregistration.ValidatingWebhookConfiguration{} }, NewFunc: func() runtime.Object { return &admissionregistration.ValidatingWebhookConfiguration{} },
NewListFunc: func() runtime.Object { return &admissionregistration.ValidatingWebhookConfigurationList{} }, NewListFunc: func() runtime.Object { return &admissionregistration.ValidatingWebhookConfigurationList{} },
@@ -45,7 +45,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -33,7 +33,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work with ControllerRevision objects. // NewREST returns a RESTStorage object that will work with ControllerRevision objects.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &apps.ControllerRevision{} }, NewFunc: func() runtime.Object { return &apps.ControllerRevision{} },
NewListFunc: func() runtime.Object { return &apps.ControllerRevisionList{} }, NewListFunc: func() runtime.Object { return &apps.ControllerRevisionList{} },
@@ -47,7 +47,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -160,7 +160,10 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
Decorator: generic.UndecoratedStorage, Decorator: generic.UndecoratedStorage,
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "controllerrevisions"} ResourcePrefix: "controllerrevisions"}
storage := NewREST(restOptions) storage, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return storage, server return storage, server
} }

View File

@@ -38,7 +38,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against DaemonSets. // NewREST returns a RESTStorage object that will work against DaemonSets.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &apps.DaemonSet{} }, NewFunc: func() runtime.Object { return &apps.DaemonSet{} },
NewListFunc: func() runtime.Object { return &apps.DaemonSetList{} }, NewListFunc: func() runtime.Object { return &apps.DaemonSetList{} },
@@ -52,13 +52,13 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = daemonset.StatusStrategy statusStore.UpdateStrategy = daemonset.StatusStrategy
return &REST{store, []string{"all"}}, &StatusREST{store: &statusStore} return &REST{store, []string{"all"}}, &StatusREST{store: &statusStore}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -39,7 +39,10 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer)
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "daemonsets", ResourcePrefix: "daemonsets",
} }
daemonSetStorage, statusStorage := NewREST(restOptions) daemonSetStorage, statusStorage, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return daemonSetStorage, statusStorage, server return daemonSetStorage, statusStorage, server
} }

View File

@@ -53,15 +53,18 @@ type DeploymentStorage struct {
Rollback *RollbackREST Rollback *RollbackREST
} }
func NewStorage(optsGetter generic.RESTOptionsGetter) DeploymentStorage { func NewStorage(optsGetter generic.RESTOptionsGetter) (DeploymentStorage, error) {
deploymentRest, deploymentStatusRest, deploymentRollbackRest := NewREST(optsGetter) deploymentRest, deploymentStatusRest, deploymentRollbackRest, err := NewREST(optsGetter)
if err != nil {
return DeploymentStorage{}, err
}
return DeploymentStorage{ return DeploymentStorage{
Deployment: deploymentRest, Deployment: deploymentRest,
Status: deploymentStatusRest, Status: deploymentStatusRest,
Scale: &ScaleREST{store: deploymentRest.Store}, Scale: &ScaleREST{store: deploymentRest.Store},
Rollback: deploymentRollbackRest, Rollback: deploymentRollbackRest,
} }, nil
} }
type REST struct { type REST struct {
@@ -70,7 +73,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against deployments. // NewREST returns a RESTStorage object that will work against deployments.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *RollbackREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *RollbackREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &apps.Deployment{} }, NewFunc: func() runtime.Object { return &apps.Deployment{} },
NewListFunc: func() runtime.Object { return &apps.DeploymentList{} }, NewListFunc: func() runtime.Object { return &apps.DeploymentList{} },
@@ -84,12 +87,12 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *Rollbac
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = deployment.StatusStrategy statusStore.UpdateStrategy = deployment.StatusStrategy
return &REST{store, []string{"all"}}, &StatusREST{store: &statusStore}, &RollbackREST{store: store} return &REST{store, []string{"all"}}, &StatusREST{store: &statusStore}, &RollbackREST{store: store}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -47,7 +47,10 @@ const defaultReplicas = 100
func newStorage(t *testing.T) (*DeploymentStorage, *etcd3testing.EtcdTestServer) { func newStorage(t *testing.T) (*DeploymentStorage, *etcd3testing.EtcdTestServer) {
etcdStorage, server := registrytest.NewEtcdStorage(t, apps.GroupName) etcdStorage, server := registrytest.NewEtcdStorage(t, apps.GroupName)
restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "deployments"} restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "deployments"}
deploymentStorage := NewStorage(restOptions) deploymentStorage, err := NewStorage(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return &deploymentStorage, server return &deploymentStorage, server
} }

View File

@@ -49,14 +49,17 @@ type ReplicaSetStorage struct {
Scale *ScaleREST Scale *ScaleREST
} }
func NewStorage(optsGetter generic.RESTOptionsGetter) ReplicaSetStorage { func NewStorage(optsGetter generic.RESTOptionsGetter) (ReplicaSetStorage, error) {
replicaSetRest, replicaSetStatusRest := NewREST(optsGetter) replicaSetRest, replicaSetStatusRest, err := NewREST(optsGetter)
if err != nil {
return ReplicaSetStorage{}, err
}
return ReplicaSetStorage{ return ReplicaSetStorage{
ReplicaSet: replicaSetRest, ReplicaSet: replicaSetRest,
Status: replicaSetStatusRest, Status: replicaSetStatusRest,
Scale: &ScaleREST{store: replicaSetRest.Store}, Scale: &ScaleREST{store: replicaSetRest.Store},
} }, nil
} }
type REST struct { type REST struct {
@@ -65,7 +68,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against ReplicaSet. // NewREST returns a RESTStorage object that will work against ReplicaSet.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &apps.ReplicaSet{} }, NewFunc: func() runtime.Object { return &apps.ReplicaSet{} },
NewListFunc: func() runtime.Object { return &apps.ReplicaSetList{} }, NewListFunc: func() runtime.Object { return &apps.ReplicaSetList{} },
@@ -80,13 +83,13 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: replicaset.GetAttrs} options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: replicaset.GetAttrs}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = replicaset.StatusStrategy statusStore.UpdateStrategy = replicaset.StatusStrategy
return &REST{store, []string{"all"}}, &StatusREST{store: &statusStore} return &REST{store, []string{"all"}}, &StatusREST{store: &statusStore}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -42,7 +42,10 @@ const defaultReplicas = 100
func newStorage(t *testing.T) (*ReplicaSetStorage, *etcd3testing.EtcdTestServer) { func newStorage(t *testing.T) (*ReplicaSetStorage, *etcd3testing.EtcdTestServer) {
etcdStorage, server := registrytest.NewEtcdStorage(t, "extensions") etcdStorage, server := registrytest.NewEtcdStorage(t, "extensions")
restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "replicasets"} restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "replicasets"}
replicaSetStorage := NewStorage(restOptions) replicaSetStorage, err := NewStorage(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return &replicaSetStorage, server return &replicaSetStorage, server
} }

View File

@@ -35,111 +35,162 @@ import (
type RESTStorageProvider struct{} type RESTStorageProvider struct{}
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apps.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apps.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(appsapiv1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(appsapiv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[appsapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[appsapiv1beta1.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(appsapiv1beta2.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(appsapiv1beta2.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[appsapiv1beta2.SchemeGroupVersion.Version] = p.v1beta2Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1beta2Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[appsapiv1beta2.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(appsapiv1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(appsapiv1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[appsapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[appsapiv1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// deployments // deployments
deploymentStorage := deploymentstore.NewStorage(restOptionsGetter) deploymentStorage, err := deploymentstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["deployments"] = deploymentStorage.Deployment storage["deployments"] = deploymentStorage.Deployment
storage["deployments/status"] = deploymentStorage.Status storage["deployments/status"] = deploymentStorage.Status
storage["deployments/rollback"] = deploymentStorage.Rollback storage["deployments/rollback"] = deploymentStorage.Rollback
storage["deployments/scale"] = deploymentStorage.Scale storage["deployments/scale"] = deploymentStorage.Scale
// statefulsets // statefulsets
statefulSetStorage := statefulsetstore.NewStorage(restOptionsGetter) statefulSetStorage, err := statefulsetstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["statefulsets"] = statefulSetStorage.StatefulSet storage["statefulsets"] = statefulSetStorage.StatefulSet
storage["statefulsets/status"] = statefulSetStorage.Status storage["statefulsets/status"] = statefulSetStorage.Status
storage["statefulsets/scale"] = statefulSetStorage.Scale storage["statefulsets/scale"] = statefulSetStorage.Scale
// controllerrevisions // controllerrevisions
historyStorage := controllerrevisionsstore.NewREST(restOptionsGetter) historyStorage, err := controllerrevisionsstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["controllerrevisions"] = historyStorage storage["controllerrevisions"] = historyStorage
return storage return storage, nil
} }
func (p RESTStorageProvider) v1beta2Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta2Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// deployments // deployments
deploymentStorage := deploymentstore.NewStorage(restOptionsGetter) deploymentStorage, err := deploymentstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["deployments"] = deploymentStorage.Deployment storage["deployments"] = deploymentStorage.Deployment
storage["deployments/status"] = deploymentStorage.Status storage["deployments/status"] = deploymentStorage.Status
storage["deployments/scale"] = deploymentStorage.Scale storage["deployments/scale"] = deploymentStorage.Scale
// statefulsets // statefulsets
statefulSetStorage := statefulsetstore.NewStorage(restOptionsGetter) statefulSetStorage, err := statefulsetstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["statefulsets"] = statefulSetStorage.StatefulSet storage["statefulsets"] = statefulSetStorage.StatefulSet
storage["statefulsets/status"] = statefulSetStorage.Status storage["statefulsets/status"] = statefulSetStorage.Status
storage["statefulsets/scale"] = statefulSetStorage.Scale storage["statefulsets/scale"] = statefulSetStorage.Scale
// daemonsets // daemonsets
daemonSetStorage, daemonSetStatusStorage := daemonsetstore.NewREST(restOptionsGetter) daemonSetStorage, daemonSetStatusStorage, err := daemonsetstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["daemonsets"] = daemonSetStorage storage["daemonsets"] = daemonSetStorage
storage["daemonsets/status"] = daemonSetStatusStorage storage["daemonsets/status"] = daemonSetStatusStorage
// replicasets // replicasets
replicaSetStorage := replicasetstore.NewStorage(restOptionsGetter) replicaSetStorage, err := replicasetstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["replicasets"] = replicaSetStorage.ReplicaSet storage["replicasets"] = replicaSetStorage.ReplicaSet
storage["replicasets/status"] = replicaSetStorage.Status storage["replicasets/status"] = replicaSetStorage.Status
storage["replicasets/scale"] = replicaSetStorage.Scale storage["replicasets/scale"] = replicaSetStorage.Scale
// controllerrevisions // controllerrevisions
historyStorage := controllerrevisionsstore.NewREST(restOptionsGetter) historyStorage, err := controllerrevisionsstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["controllerrevisions"] = historyStorage storage["controllerrevisions"] = historyStorage
return storage return storage, nil
} }
func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// deployments // deployments
deploymentStorage := deploymentstore.NewStorage(restOptionsGetter) deploymentStorage, err := deploymentstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["deployments"] = deploymentStorage.Deployment storage["deployments"] = deploymentStorage.Deployment
storage["deployments/status"] = deploymentStorage.Status storage["deployments/status"] = deploymentStorage.Status
storage["deployments/scale"] = deploymentStorage.Scale storage["deployments/scale"] = deploymentStorage.Scale
// statefulsets // statefulsets
statefulSetStorage := statefulsetstore.NewStorage(restOptionsGetter) statefulSetStorage, err := statefulsetstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["statefulsets"] = statefulSetStorage.StatefulSet storage["statefulsets"] = statefulSetStorage.StatefulSet
storage["statefulsets/status"] = statefulSetStorage.Status storage["statefulsets/status"] = statefulSetStorage.Status
storage["statefulsets/scale"] = statefulSetStorage.Scale storage["statefulsets/scale"] = statefulSetStorage.Scale
// daemonsets // daemonsets
daemonSetStorage, daemonSetStatusStorage := daemonsetstore.NewREST(restOptionsGetter) daemonSetStorage, daemonSetStatusStorage, err := daemonsetstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["daemonsets"] = daemonSetStorage storage["daemonsets"] = daemonSetStorage
storage["daemonsets/status"] = daemonSetStatusStorage storage["daemonsets/status"] = daemonSetStatusStorage
// replicasets // replicasets
replicaSetStorage := replicasetstore.NewStorage(restOptionsGetter) replicaSetStorage, err := replicasetstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["replicasets"] = replicaSetStorage.ReplicaSet storage["replicasets"] = replicaSetStorage.ReplicaSet
storage["replicasets/status"] = replicaSetStorage.Status storage["replicasets/status"] = replicaSetStorage.Status
storage["replicasets/scale"] = replicaSetStorage.Scale storage["replicasets/scale"] = replicaSetStorage.Scale
// controllerrevisions // controllerrevisions
historyStorage := controllerrevisionsstore.NewREST(restOptionsGetter) historyStorage, err := controllerrevisionsstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["controllerrevisions"] = historyStorage storage["controllerrevisions"] = historyStorage
return storage return storage, nil
} }
func (p RESTStorageProvider) GroupName() string { func (p RESTStorageProvider) GroupName() string {

View File

@@ -46,14 +46,17 @@ type StatefulSetStorage struct {
Scale *ScaleREST Scale *ScaleREST
} }
func NewStorage(optsGetter generic.RESTOptionsGetter) StatefulSetStorage { func NewStorage(optsGetter generic.RESTOptionsGetter) (StatefulSetStorage, error) {
statefulSetRest, statefulSetStatusRest := NewREST(optsGetter) statefulSetRest, statefulSetStatusRest, err := NewREST(optsGetter)
if err != nil {
return StatefulSetStorage{}, err
}
return StatefulSetStorage{ return StatefulSetStorage{
StatefulSet: statefulSetRest, StatefulSet: statefulSetRest,
Status: statefulSetStatusRest, Status: statefulSetStatusRest,
Scale: &ScaleREST{store: statefulSetRest.Store}, Scale: &ScaleREST{store: statefulSetRest.Store},
} }, nil
} }
// rest implements a RESTStorage for statefulsets against etcd // rest implements a RESTStorage for statefulsets against etcd
@@ -62,7 +65,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against statefulsets. // NewREST returns a RESTStorage object that will work against statefulsets.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &apps.StatefulSet{} }, NewFunc: func() runtime.Object { return &apps.StatefulSet{} },
NewListFunc: func() runtime.Object { return &apps.StatefulSetList{} }, NewListFunc: func() runtime.Object { return &apps.StatefulSetList{} },
@@ -76,12 +79,12 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = statefulset.StatusStrategy statusStore.UpdateStrategy = statefulset.StatusStrategy
return &REST{store}, &StatusREST{store: &statusStore} return &REST{store}, &StatusREST{store: &statusStore}, nil
} }
// Implement CategoriesProvider // Implement CategoriesProvider

View File

@@ -40,7 +40,10 @@ import (
func newStorage(t *testing.T) (StatefulSetStorage, *etcd3testing.EtcdTestServer) { func newStorage(t *testing.T) (StatefulSetStorage, *etcd3testing.EtcdTestServer) {
etcdStorage, server := registrytest.NewEtcdStorage(t, apps.GroupName) etcdStorage, server := registrytest.NewEtcdStorage(t, apps.GroupName)
restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "statefulsets"} restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "statefulsets"}
storage := NewStorage(restOptions) storage, err := NewStorage(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return storage, server return storage, server
} }

View File

@@ -30,7 +30,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against audit sinks // NewREST returns a RESTStorage object that will work against audit sinks
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &auditregistration.AuditSink{} }, NewFunc: func() runtime.Object { return &auditregistration.AuditSink{} },
NewListFunc: func() runtime.Object { return &auditregistration.AuditSinkList{} }, NewListFunc: func() runtime.Object { return &auditregistration.AuditSinkList{} },
@@ -45,7 +45,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -30,21 +30,25 @@ import (
type RESTStorageProvider struct{} type RESTStorageProvider struct{}
// NewRESTStorage returns a RESTStorageProvider // NewRESTStorage returns a RESTStorageProvider
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(auditv1alpha1.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(auditv1alpha1.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
if apiResourceConfigSource.VersionEnabled(auditv1alpha1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(auditv1alpha1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[auditv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[auditv1alpha1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
s := auditstorage.NewREST(restOptionsGetter) s, err := auditstorage.NewREST(restOptionsGetter)
storage["auditsinks"] = s storage["auditsinks"] = s
return storage return storage, err
} }
// GroupName is the group name for the storage provider // GroupName is the group name for the storage provider

View File

@@ -34,7 +34,7 @@ type RESTStorageProvider struct {
APIAudiences authenticator.Audiences APIAudiences authenticator.Audiences
} }
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
// TODO figure out how to make the swagger generation stable, while allowing this endpoint to be disabled. // TODO figure out how to make the swagger generation stable, while allowing this endpoint to be disabled.
// if p.Authenticator == nil { // if p.Authenticator == nil {
// return genericapiserver.APIGroupInfo{}, false // return genericapiserver.APIGroupInfo{}, false
@@ -51,7 +51,7 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorag
apiGroupInfo.VersionedResourcesStorageMap[authenticationv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) apiGroupInfo.VersionedResourcesStorageMap[authenticationv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter)
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage {

View File

@@ -37,9 +37,9 @@ type RESTStorageProvider struct {
RuleResolver authorizer.RuleResolver RuleResolver authorizer.RuleResolver
} }
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
if p.Authorizer == nil { if p.Authorizer == nil {
return genericapiserver.APIGroupInfo{}, false return genericapiserver.APIGroupInfo{}, false, nil
} }
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(authorization.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(authorization.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
@@ -54,7 +54,7 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorag
apiGroupInfo.VersionedResourcesStorageMap[authorizationv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) apiGroupInfo.VersionedResourcesStorageMap[authorizationv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter)
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage {

View File

@@ -37,7 +37,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against horizontal pod autoscalers. // NewREST returns a RESTStorage object that will work against horizontal pod autoscalers.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscaler{} }, NewFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscaler{} },
NewListFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscalerList{} }, NewListFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscalerList{} },
@@ -51,12 +51,12 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = horizontalpodautoscaler.StatusStrategy statusStore.UpdateStrategy = horizontalpodautoscaler.StatusStrategy
return &REST{store}, &StatusREST{store: &statusStore} return &REST{store}, &StatusREST{store: &statusStore}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -45,7 +45,10 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer)
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "horizontalpodautoscalers", ResourcePrefix: "horizontalpodautoscalers",
} }
horizontalPodAutoscalerStorage, statusStorage := NewREST(restOptions) horizontalPodAutoscalerStorage, statusStorage, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return horizontalPodAutoscalerStorage, statusStorage, server return horizontalPodAutoscalerStorage, statusStorage, server
} }

View File

@@ -31,52 +31,73 @@ import (
type RESTStorageProvider struct{} type RESTStorageProvider struct{}
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(autoscaling.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(autoscaling.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(autoscalingapiv2beta2.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(autoscalingapiv2beta2.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv2beta2.SchemeGroupVersion.Version] = p.v2beta2Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v2beta2Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv2beta2.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(autoscalingapiv2beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(autoscalingapiv2beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv2beta1.SchemeGroupVersion.Version] = p.v2beta1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v2beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv2beta1.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(autoscalingapiv1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(autoscalingapiv1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// horizontalpodautoscalers // horizontalpodautoscalers
hpaStorage, hpaStatusStorage := horizontalpodautoscalerstore.NewREST(restOptionsGetter) hpaStorage, hpaStatusStorage, err := horizontalpodautoscalerstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["horizontalpodautoscalers"] = hpaStorage storage["horizontalpodautoscalers"] = hpaStorage
storage["horizontalpodautoscalers/status"] = hpaStatusStorage storage["horizontalpodautoscalers/status"] = hpaStatusStorage
return storage return storage, err
} }
func (p RESTStorageProvider) v2beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v2beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// horizontalpodautoscalers // horizontalpodautoscalers
hpaStorage, hpaStatusStorage := horizontalpodautoscalerstore.NewREST(restOptionsGetter) hpaStorage, hpaStatusStorage, err := horizontalpodautoscalerstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["horizontalpodautoscalers"] = hpaStorage storage["horizontalpodautoscalers"] = hpaStorage
storage["horizontalpodautoscalers/status"] = hpaStatusStorage storage["horizontalpodautoscalers/status"] = hpaStatusStorage
return storage return storage, err
} }
func (p RESTStorageProvider) v2beta2Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v2beta2Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// horizontalpodautoscalers // horizontalpodautoscalers
hpaStorage, hpaStatusStorage := horizontalpodautoscalerstore.NewREST(restOptionsGetter) hpaStorage, hpaStatusStorage, err := horizontalpodautoscalerstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["horizontalpodautoscalers"] = hpaStorage storage["horizontalpodautoscalers"] = hpaStorage
storage["horizontalpodautoscalers/status"] = hpaStatusStorage storage["horizontalpodautoscalers/status"] = hpaStatusStorage
return storage return storage, err
} }
func (p RESTStorageProvider) GroupName() string { func (p RESTStorageProvider) GroupName() string {

View File

@@ -37,7 +37,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against CronJobs. // NewREST returns a RESTStorage object that will work against CronJobs.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &batch.CronJob{} }, NewFunc: func() runtime.Object { return &batch.CronJob{} },
NewListFunc: func() runtime.Object { return &batch.CronJobList{} }, NewListFunc: func() runtime.Object { return &batch.CronJobList{} },
@@ -51,13 +51,13 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = cronjob.StatusStrategy statusStore.UpdateStrategy = cronjob.StatusStrategy
return &REST{store}, &StatusREST{store: &statusStore} return &REST{store}, &StatusREST{store: &statusStore}, nil
} }
var _ rest.CategoriesProvider = &REST{} var _ rest.CategoriesProvider = &REST{}

View File

@@ -40,7 +40,10 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer)
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "cronjobs", ResourcePrefix: "cronjobs",
} }
storage, statusStorage := NewREST(restOptions) storage, statusStorage, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return storage, statusStorage, server return storage, statusStorage, server
} }

View File

@@ -38,13 +38,16 @@ type JobStorage struct {
} }
// NewStorage creates a new JobStorage against etcd. // NewStorage creates a new JobStorage against etcd.
func NewStorage(optsGetter generic.RESTOptionsGetter) JobStorage { func NewStorage(optsGetter generic.RESTOptionsGetter) (JobStorage, error) {
jobRest, jobStatusRest := NewREST(optsGetter) jobRest, jobStatusRest, err := NewREST(optsGetter)
if err != nil {
return JobStorage{}, err
}
return JobStorage{ return JobStorage{
Job: jobRest, Job: jobRest,
Status: jobStatusRest, Status: jobStatusRest,
} }, nil
} }
// REST implements a RESTStorage for jobs against etcd // REST implements a RESTStorage for jobs against etcd
@@ -53,7 +56,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against Jobs. // NewREST returns a RESTStorage object that will work against Jobs.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &batch.Job{} }, NewFunc: func() runtime.Object { return &batch.Job{} },
NewListFunc: func() runtime.Object { return &batch.JobList{} }, NewListFunc: func() runtime.Object { return &batch.JobList{} },
@@ -68,13 +71,13 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: job.GetAttrs} options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: job.GetAttrs}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = job.StatusStrategy statusStore.UpdateStrategy = job.StatusStrategy
return &REST{store}, &StatusREST{store: &statusStore} return &REST{store}, &StatusREST{store: &statusStore}, nil
} }
// Implement CategoriesProvider // Implement CategoriesProvider

View File

@@ -39,7 +39,10 @@ func newStorage(t *testing.T) (*JobStorage, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "jobs", ResourcePrefix: "jobs",
} }
jobStorage := NewStorage(restOptions) jobStorage, err := NewStorage(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return &jobStorage, server return &jobStorage, server
} }

View File

@@ -32,52 +32,73 @@ import (
type RESTStorageProvider struct{} type RESTStorageProvider struct{}
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(batch.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(batch.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(batchapiv1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(batchapiv1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[batchapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[batchapiv1.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(batchapiv1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(batchapiv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[batchapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[batchapiv1beta1.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(batchapiv2alpha1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(batchapiv2alpha1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[batchapiv2alpha1.SchemeGroupVersion.Version] = p.v2alpha1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v2alpha1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[batchapiv2alpha1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// jobs // jobs
jobsStorage, jobsStatusStorage := jobstore.NewREST(restOptionsGetter) jobsStorage, jobsStatusStorage, err := jobstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["jobs"] = jobsStorage storage["jobs"] = jobsStorage
storage["jobs/status"] = jobsStatusStorage storage["jobs/status"] = jobsStatusStorage
return storage return storage, err
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// cronjobs // cronjobs
cronJobsStorage, cronJobsStatusStorage := cronjobstore.NewREST(restOptionsGetter) cronJobsStorage, cronJobsStatusStorage, err := cronjobstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["cronjobs"] = cronJobsStorage storage["cronjobs"] = cronJobsStorage
storage["cronjobs/status"] = cronJobsStatusStorage storage["cronjobs/status"] = cronJobsStatusStorage
return storage return storage, err
} }
func (p RESTStorageProvider) v2alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v2alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// cronjobs // cronjobs
cronJobsStorage, cronJobsStatusStorage := cronjobstore.NewREST(restOptionsGetter) cronJobsStorage, cronJobsStatusStorage, err := cronjobstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["cronjobs"] = cronJobsStorage storage["cronjobs"] = cronJobsStorage
storage["cronjobs/status"] = cronJobsStatusStorage storage["cronjobs/status"] = cronJobsStatusStorage
return storage return storage, err
} }
func (p RESTStorageProvider) GroupName() string { func (p RESTStorageProvider) GroupName() string {

View File

@@ -37,7 +37,7 @@ type REST struct {
} }
// NewREST returns a registry which will store CertificateSigningRequest in the given helper // NewREST returns a registry which will store CertificateSigningRequest in the given helper
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *ApprovalREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *ApprovalREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &certificates.CertificateSigningRequest{} }, NewFunc: func() runtime.Object { return &certificates.CertificateSigningRequest{} },
NewListFunc: func() runtime.Object { return &certificates.CertificateSigningRequestList{} }, NewListFunc: func() runtime.Object { return &certificates.CertificateSigningRequestList{} },
@@ -52,7 +52,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *Approva
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, nil, err
} }
// Subresources use the same store and creation strategy, which only // Subresources use the same store and creation strategy, which only
@@ -64,7 +64,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *Approva
approvalStore := *store approvalStore := *store
approvalStore.UpdateStrategy = csrregistry.ApprovalStrategy approvalStore.UpdateStrategy = csrregistry.ApprovalStrategy
return &REST{store}, &StatusREST{store: &statusStore}, &ApprovalREST{store: &approvalStore} return &REST{store}, &StatusREST{store: &statusStore}, &ApprovalREST{store: &approvalStore}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -29,27 +29,34 @@ import (
type RESTStorageProvider struct{} type RESTStorageProvider struct{}
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(certificates.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(certificates.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(certificatesapiv1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(certificatesapiv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1beta1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// certificatesigningrequests // certificatesigningrequests
csrStorage, csrStatusStorage, csrApprovalStorage := certificatestore.NewREST(restOptionsGetter) csrStorage, csrStatusStorage, csrApprovalStorage, err := certificatestore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["certificatesigningrequests"] = csrStorage storage["certificatesigningrequests"] = csrStorage
storage["certificatesigningrequests/status"] = csrStatusStorage storage["certificatesigningrequests/status"] = csrStatusStorage
storage["certificatesigningrequests/approval"] = csrApprovalStorage storage["certificatesigningrequests/approval"] = csrApprovalStorage
return storage return storage, err
} }
func (p RESTStorageProvider) GroupName() string { func (p RESTStorageProvider) GroupName() string {

View File

@@ -33,7 +33,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against leases. // NewREST returns a RESTStorage object that will work against leases.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &coordinationapi.Lease{} }, NewFunc: func() runtime.Object { return &coordinationapi.Lease{} },
NewListFunc: func() runtime.Object { return &coordinationapi.LeaseList{} }, NewListFunc: func() runtime.Object { return &coordinationapi.LeaseList{} },
@@ -47,8 +47,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -30,36 +30,50 @@ import (
type RESTStorageProvider struct{} type RESTStorageProvider struct{}
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(coordination.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(coordination.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(coordinationv1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(coordinationv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[coordinationv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[coordinationv1beta1.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(coordinationv1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(coordinationv1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[coordinationv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[coordinationv1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// leases // leases
leaseStorage := leasestorage.NewREST(restOptionsGetter) leaseStorage, err := leasestorage.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["leases"] = leaseStorage storage["leases"] = leaseStorage
return storage return storage, err
} }
func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// leases // leases
leaseStorage := leasestorage.NewREST(restOptionsGetter) leaseStorage, err := leasestorage.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["leases"] = leaseStorage storage["leases"] = leaseStorage
return storage return storage, err
} }
func (p RESTStorageProvider) GroupName() string { func (p RESTStorageProvider) GroupName() string {

View File

@@ -35,7 +35,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work with ConfigMap objects. // NewREST returns a RESTStorage object that will work with ConfigMap objects.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.ConfigMap{} }, NewFunc: func() runtime.Object { return &api.ConfigMap{} },
NewListFunc: func() runtime.Object { return &api.ConfigMapList{} }, NewListFunc: func() runtime.Object { return &api.ConfigMapList{} },
@@ -53,9 +53,9 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
TriggerFunc: map[string]storage.IndexerFunc{"metadata.name": configmap.NameTriggerFunc}, TriggerFunc: map[string]storage.IndexerFunc{"metadata.name": configmap.NameTriggerFunc},
} }
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -38,7 +38,11 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "configmaps", ResourcePrefix: "configmaps",
} }
return NewREST(restOptions), server rest, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return rest, server
} }
func validNewConfigMap() *api.ConfigMap { func validNewConfigMap() *api.ConfigMap {

View File

@@ -33,7 +33,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against endpoints. // NewREST returns a RESTStorage object that will work against endpoints.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.Endpoints{} }, NewFunc: func() runtime.Object { return &api.Endpoints{} },
NewListFunc: func() runtime.Object { return &api.EndpointsList{} }, NewListFunc: func() runtime.Object { return &api.EndpointsList{} },
@@ -47,9 +47,9 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -38,7 +38,11 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "endpoints", ResourcePrefix: "endpoints",
} }
return NewREST(restOptions), server rest, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return rest, server
} }
func validNewEndpoints() *api.Endpoints { func validNewEndpoints() *api.Endpoints {

View File

@@ -33,11 +33,11 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against events. // NewREST returns a RESTStorage object that will work against events.
func NewREST(optsGetter generic.RESTOptionsGetter, ttl uint64) *REST { func NewREST(optsGetter generic.RESTOptionsGetter, ttl uint64) (*REST, error) {
resource := api.Resource("events") resource := api.Resource("events")
opts, err := optsGetter.GetRESTOptions(resource) opts, err := optsGetter.GetRESTOptions(resource)
if err != nil { if err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
store := &genericregistry.Store{ store := &genericregistry.Store{
@@ -57,9 +57,9 @@ func NewREST(optsGetter generic.RESTOptionsGetter, ttl uint64) *REST {
} }
options := &generic.StoreOptions{RESTOptions: opts, AttrFunc: event.GetAttrs} // Pass in opts to use UndecoratedStorage options := &generic.StoreOptions{RESTOptions: opts, AttrFunc: event.GetAttrs} // Pass in opts to use UndecoratedStorage
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -38,7 +38,11 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "events", ResourcePrefix: "events",
} }
return NewREST(restOptions, testTTL), server rest, err := NewREST(restOptions, testTTL)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return rest, server
} }
func validNewEvent(namespace string) *api.Event { func validNewEvent(namespace string) *api.Event {

View File

@@ -30,7 +30,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against limitranges. // NewREST returns a RESTStorage object that will work against limitranges.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.LimitRange{} }, NewFunc: func() runtime.Object { return &api.LimitRange{} },
NewListFunc: func() runtime.Object { return &api.LimitRangeList{} }, NewListFunc: func() runtime.Object { return &api.LimitRangeList{} },
@@ -43,9 +43,9 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -39,7 +39,11 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "limitranges", ResourcePrefix: "limitranges",
} }
return NewREST(restOptions), server rest, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return rest, server
} }
func validNewLimitRange() *api.LimitRange { func validNewLimitRange() *api.LimitRange {

View File

@@ -58,7 +58,7 @@ type FinalizeREST struct {
} }
// NewREST returns a RESTStorage object that will work against namespaces. // NewREST returns a RESTStorage object that will work against namespaces.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *FinalizeREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *FinalizeREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.Namespace{} }, NewFunc: func() runtime.Object { return &api.Namespace{} },
NewListFunc: func() runtime.Object { return &api.NamespaceList{} }, NewListFunc: func() runtime.Object { return &api.NamespaceList{} },
@@ -76,7 +76,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *Finaliz
} }
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: namespace.GetAttrs} options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: namespace.GetAttrs}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, nil, err
} }
statusStore := *store statusStore := *store
@@ -85,7 +85,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *Finaliz
finalizeStore := *store finalizeStore := *store
finalizeStore.UpdateStrategy = namespace.FinalizeStrategy finalizeStore.UpdateStrategy = namespace.FinalizeStrategy
return &REST{store: store, status: &statusStore}, &StatusREST{store: &statusStore}, &FinalizeREST{store: &finalizeStore} return &REST{store: store, status: &statusStore}, &StatusREST{store: &statusStore}, &FinalizeREST{store: &finalizeStore}, nil
} }
func (r *REST) NamespaceScoped() bool { func (r *REST) NamespaceScoped() bool {

View File

@@ -37,7 +37,10 @@ import (
func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) { func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
etcdStorage, server := registrytest.NewEtcdStorage(t, "") etcdStorage, server := registrytest.NewEtcdStorage(t, "")
restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "namespaces"} restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "namespaces"}
namespaceStorage, _, _ := NewREST(restOptions) namespaceStorage, _, _, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return namespaceStorage, server return namespaceStorage, server
} }
@@ -278,7 +281,10 @@ func TestFinalizeDeletingNamespaceWithCompleteFinalizers(t *testing.T) {
// get finalize storage // get finalize storage
etcdStorage, server := registrytest.NewEtcdStorage(t, "") etcdStorage, server := registrytest.NewEtcdStorage(t, "")
restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "namespaces"} restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "namespaces"}
storage, _, finalizeStorage := NewREST(restOptions) storage, _, finalizeStorage, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
defer server.Terminate(t) defer server.Terminate(t)
defer storage.store.DestroyFunc() defer storage.store.DestroyFunc()
@@ -318,7 +324,10 @@ func TestFinalizeDeletingNamespaceWithIncompleteMetadataFinalizers(t *testing.T)
// get finalize storage // get finalize storage
etcdStorage, server := registrytest.NewEtcdStorage(t, "") etcdStorage, server := registrytest.NewEtcdStorage(t, "")
restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "namespaces"} restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "namespaces"}
storage, _, finalizeStorage := NewREST(restOptions) storage, _, finalizeStorage, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
defer server.Terminate(t) defer server.Terminate(t)
defer storage.store.DestroyFunc() defer storage.store.DestroyFunc()

View File

@@ -36,7 +36,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against persistent volumes. // NewREST returns a RESTStorage object that will work against persistent volumes.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.PersistentVolume{} }, NewFunc: func() runtime.Object { return &api.PersistentVolume{} },
NewListFunc: func() runtime.Object { return &api.PersistentVolumeList{} }, NewListFunc: func() runtime.Object { return &api.PersistentVolumeList{} },
@@ -52,13 +52,13 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: persistentvolume.GetAttrs} options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: persistentvolume.GetAttrs}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = persistentvolume.StatusStrategy statusStore.UpdateStrategy = persistentvolume.StatusStrategy
return &REST{store}, &StatusREST{store: &statusStore} return &REST{store}, &StatusREST{store: &statusStore}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -43,7 +43,10 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer)
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "persistentvolumes", ResourcePrefix: "persistentvolumes",
} }
persistentVolumeStorage, statusStorage := NewREST(restOptions) persistentVolumeStorage, statusStorage, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return persistentVolumeStorage, statusStorage, server return persistentVolumeStorage, statusStorage, server
} }

View File

@@ -36,7 +36,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against persistent volume claims. // NewREST returns a RESTStorage object that will work against persistent volume claims.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.PersistentVolumeClaim{} }, NewFunc: func() runtime.Object { return &api.PersistentVolumeClaim{} },
NewListFunc: func() runtime.Object { return &api.PersistentVolumeClaimList{} }, NewListFunc: func() runtime.Object { return &api.PersistentVolumeClaimList{} },
@@ -52,13 +52,13 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: persistentvolumeclaim.GetAttrs} options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: persistentvolumeclaim.GetAttrs}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = persistentvolumeclaim.StatusStrategy statusStore.UpdateStrategy = persistentvolumeclaim.StatusStrategy
return &REST{store}, &StatusREST{store: &statusStore} return &REST{store}, &StatusREST{store: &statusStore}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -43,7 +43,10 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer)
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "persistentvolumeclaims", ResourcePrefix: "persistentvolumeclaims",
} }
persistentVolumeClaimStorage, statusStorage := NewREST(restOptions) persistentVolumeClaimStorage, statusStorage, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return persistentVolumeClaimStorage, statusStorage, server return persistentVolumeClaimStorage, statusStorage, server
} }

View File

@@ -170,7 +170,10 @@ func newFailDeleteUpdateStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServ
DeleteCollectionWorkers: 3, DeleteCollectionWorkers: 3,
ResourcePrefix: "pods", ResourcePrefix: "pods",
} }
storage := NewStorage(restOptions, nil, nil, nil) storage, err := NewStorage(restOptions, nil, nil, nil)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
storage.Pod.Store.Storage = genericregistry.DryRunnableStorage{ storage.Pod.Store.Storage = genericregistry.DryRunnableStorage{
Storage: FailDeleteUpdateStorage{storage.Pod.Store.Storage.Storage}, Storage: FailDeleteUpdateStorage{storage.Pod.Store.Storage.Storage},
Codec: apitesting.TestStorageCodec(codecs, examplev1.SchemeGroupVersion), Codec: apitesting.TestStorageCodec(codecs, examplev1.SchemeGroupVersion),

View File

@@ -66,7 +66,7 @@ type REST struct {
} }
// NewStorage returns a RESTStorage object that will work against pods. // NewStorage returns a RESTStorage object that will work against pods.
func NewStorage(optsGetter generic.RESTOptionsGetter, k client.ConnectionInfoGetter, proxyTransport http.RoundTripper, podDisruptionBudgetClient policyclient.PodDisruptionBudgetsGetter) PodStorage { func NewStorage(optsGetter generic.RESTOptionsGetter, k client.ConnectionInfoGetter, proxyTransport http.RoundTripper, podDisruptionBudgetClient policyclient.PodDisruptionBudgetsGetter) (PodStorage, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.Pod{} }, NewFunc: func() runtime.Object { return &api.Pod{} },
@@ -87,7 +87,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter, k client.ConnectionInfoGet
TriggerFunc: map[string]storage.IndexerFunc{"spec.nodeName": pod.NodeNameTriggerFunc}, TriggerFunc: map[string]storage.IndexerFunc{"spec.nodeName": pod.NodeNameTriggerFunc},
} }
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return PodStorage{}, err
} }
statusStore := *store statusStore := *store
@@ -106,7 +106,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter, k client.ConnectionInfoGet
Exec: &podrest.ExecREST{Store: store, KubeletConn: k}, Exec: &podrest.ExecREST{Store: store, KubeletConn: k},
Attach: &podrest.AttachREST{Store: store, KubeletConn: k}, Attach: &podrest.AttachREST{Store: store, KubeletConn: k},
PortForward: &podrest.PortForwardREST{Store: store, KubeletConn: k}, PortForward: &podrest.PortForwardREST{Store: store, KubeletConn: k},
} }, nil
} }
// Implement Redirector. // Implement Redirector.

View File

@@ -52,7 +52,10 @@ func newStorage(t *testing.T) (*REST, *BindingREST, *StatusREST, *etcd3testing.E
DeleteCollectionWorkers: 3, DeleteCollectionWorkers: 3,
ResourcePrefix: "pods", ResourcePrefix: "pods",
} }
storage := NewStorage(restOptions, nil, nil, nil) storage, err := NewStorage(restOptions, nil, nil, nil)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return storage.Pod, storage.Binding, storage.Status, server return storage.Pod, storage.Binding, storage.Status, server
} }
@@ -169,7 +172,10 @@ func newFailDeleteStorage(t *testing.T, called *bool) (*REST, *etcd3testing.Etcd
DeleteCollectionWorkers: 3, DeleteCollectionWorkers: 3,
ResourcePrefix: "pods", ResourcePrefix: "pods",
} }
storage := NewStorage(restOptions, nil, nil, nil) storage, err := NewStorage(restOptions, nil, nil, nil)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
storage.Pod.Store.Storage = genericregistry.DryRunnableStorage{Storage: FailDeletionStorage{storage.Pod.Store.Storage.Storage, called}} storage.Pod.Store.Storage = genericregistry.DryRunnableStorage{Storage: FailDeletionStorage{storage.Pod.Store.Storage.Storage, called}}
return storage.Pod, server return storage.Pod, server
} }

View File

@@ -32,7 +32,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against pod templates. // NewREST returns a RESTStorage object that will work against pod templates.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.PodTemplate{} }, NewFunc: func() runtime.Object { return &api.PodTemplate{} },
NewListFunc: func() runtime.Object { return &api.PodTemplateList{} }, NewListFunc: func() runtime.Object { return &api.PodTemplateList{} },
@@ -49,7 +49,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -38,7 +38,11 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "podtemplates", ResourcePrefix: "podtemplates",
} }
return NewREST(restOptions), server rest, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return rest, server
} }
func validNewPodTemplate(name string) *api.PodTemplate { func validNewPodTemplate(name string) *api.PodTemplate {

View File

@@ -48,14 +48,17 @@ type ControllerStorage struct {
Scale *ScaleREST Scale *ScaleREST
} }
func NewStorage(optsGetter generic.RESTOptionsGetter) ControllerStorage { func NewStorage(optsGetter generic.RESTOptionsGetter) (ControllerStorage, error) {
controllerREST, statusREST := NewREST(optsGetter) controllerREST, statusREST, err := NewREST(optsGetter)
if err != nil {
return ControllerStorage{}, err
}
return ControllerStorage{ return ControllerStorage{
Controller: controllerREST, Controller: controllerREST,
Status: statusREST, Status: statusREST,
Scale: &ScaleREST{store: controllerREST.Store}, Scale: &ScaleREST{store: controllerREST.Store},
} }, nil
} }
type REST struct { type REST struct {
@@ -63,7 +66,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against replication controllers. // NewREST returns a RESTStorage object that will work against replication controllers.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.ReplicationController{} }, NewFunc: func() runtime.Object { return &api.ReplicationController{} },
NewListFunc: func() runtime.Object { return &api.ReplicationControllerList{} }, NewListFunc: func() runtime.Object { return &api.ReplicationControllerList{} },
@@ -78,13 +81,13 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: replicationcontroller.GetAttrs} options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: replicationcontroller.GetAttrs}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = replicationcontroller.StatusStrategy statusStore.UpdateStrategy = replicationcontroller.StatusStrategy
return &REST{store}, &StatusREST{store: &statusStore} return &REST{store}, &StatusREST{store: &statusStore}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -49,7 +49,10 @@ func newStorage(t *testing.T) (ControllerStorage, *etcd3testing.EtcdTestServer)
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "replicationcontrollers", ResourcePrefix: "replicationcontrollers",
} }
storage := NewStorage(restOptions) storage, err := NewStorage(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return storage, server return storage, server
} }

View File

@@ -33,7 +33,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against resource quotas. // NewREST returns a RESTStorage object that will work against resource quotas.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.ResourceQuota{} }, NewFunc: func() runtime.Object { return &api.ResourceQuota{} },
NewListFunc: func() runtime.Object { return &api.ResourceQuotaList{} }, NewListFunc: func() runtime.Object { return &api.ResourceQuotaList{} },
@@ -46,13 +46,13 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = resourcequota.StatusStrategy statusStore.UpdateStrategy = resourcequota.StatusStrategy
return &REST{store}, &StatusREST{store: &statusStore} return &REST{store}, &StatusREST{store: &statusStore}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -42,7 +42,10 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer)
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "resourcequotas", ResourcePrefix: "resourcequotas",
} }
resourceQuotaStorage, statusStorage := NewREST(restOptions) resourceQuotaStorage, statusStorage, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return resourceQuotaStorage, statusStorage, server return resourceQuotaStorage, statusStorage, server
} }

View File

@@ -115,41 +115,80 @@ func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter generi
} }
restStorage := LegacyRESTStorage{} restStorage := LegacyRESTStorage{}
podTemplateStorage := podtemplatestore.NewREST(restOptionsGetter) podTemplateStorage, err := podtemplatestore.NewREST(restOptionsGetter)
if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
}
eventStorage := eventstore.NewREST(restOptionsGetter, uint64(c.EventTTL.Seconds())) eventStorage, err := eventstore.NewREST(restOptionsGetter, uint64(c.EventTTL.Seconds()))
limitRangeStorage := limitrangestore.NewREST(restOptionsGetter) if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
}
limitRangeStorage, err := limitrangestore.NewREST(restOptionsGetter)
if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
}
resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotastore.NewREST(restOptionsGetter) resourceQuotaStorage, resourceQuotaStatusStorage, err := resourcequotastore.NewREST(restOptionsGetter)
secretStorage := secretstore.NewREST(restOptionsGetter) if err != nil {
persistentVolumeStorage, persistentVolumeStatusStorage := pvstore.NewREST(restOptionsGetter) return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
persistentVolumeClaimStorage, persistentVolumeClaimStatusStorage := pvcstore.NewREST(restOptionsGetter) }
configMapStorage := configmapstore.NewREST(restOptionsGetter) secretStorage, err := secretstore.NewREST(restOptionsGetter)
if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
}
persistentVolumeStorage, persistentVolumeStatusStorage, err := pvstore.NewREST(restOptionsGetter)
if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
}
persistentVolumeClaimStorage, persistentVolumeClaimStatusStorage, err := pvcstore.NewREST(restOptionsGetter)
if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
}
configMapStorage, err := configmapstore.NewREST(restOptionsGetter)
if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
}
namespaceStorage, namespaceStatusStorage, namespaceFinalizeStorage := namespacestore.NewREST(restOptionsGetter) namespaceStorage, namespaceStatusStorage, namespaceFinalizeStorage, err := namespacestore.NewREST(restOptionsGetter)
if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
}
endpointsStorage := endpointsstore.NewREST(restOptionsGetter) endpointsStorage, err := endpointsstore.NewREST(restOptionsGetter)
if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
}
nodeStorage, err := nodestore.NewStorage(restOptionsGetter, c.KubeletClientConfig, c.ProxyTransport) nodeStorage, err := nodestore.NewStorage(restOptionsGetter, c.KubeletClientConfig, c.ProxyTransport)
if err != nil { if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
} }
podStorage := podstore.NewStorage( podStorage, err := podstore.NewStorage(
restOptionsGetter, restOptionsGetter,
nodeStorage.KubeletConnectionInfo, nodeStorage.KubeletConnectionInfo,
c.ProxyTransport, c.ProxyTransport,
podDisruptionClient, podDisruptionClient,
) )
if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
}
var serviceAccountStorage *serviceaccountstore.REST var serviceAccountStorage *serviceaccountstore.REST
if c.ServiceAccountIssuer != nil && utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) { if c.ServiceAccountIssuer != nil && utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) {
serviceAccountStorage = serviceaccountstore.NewREST(restOptionsGetter, c.ServiceAccountIssuer, c.APIAudiences, c.ServiceAccountMaxExpiration, podStorage.Pod.Store, secretStorage.Store) serviceAccountStorage, err = serviceaccountstore.NewREST(restOptionsGetter, c.ServiceAccountIssuer, c.APIAudiences, c.ServiceAccountMaxExpiration, podStorage.Pod.Store, secretStorage.Store)
} else { } else {
serviceAccountStorage = serviceaccountstore.NewREST(restOptionsGetter, nil, nil, 0, nil, nil) serviceAccountStorage, err = serviceaccountstore.NewREST(restOptionsGetter, nil, nil, 0, nil, nil)
}
if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
} }
serviceRESTStorage, serviceStatusStorage := servicestore.NewGenericREST(restOptionsGetter) serviceRESTStorage, serviceStatusStorage, err := servicestore.NewGenericREST(restOptionsGetter)
if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
}
var serviceClusterIPRegistry rangeallocation.RangeRegistry var serviceClusterIPRegistry rangeallocation.RangeRegistry
serviceClusterIPRange := c.ServiceIPRange serviceClusterIPRange := c.ServiceIPRange
@@ -181,7 +220,10 @@ func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter generi
}) })
restStorage.ServiceNodePortAllocator = serviceNodePortRegistry restStorage.ServiceNodePortAllocator = serviceNodePortRegistry
controllerStorage := controllerstore.NewStorage(restOptionsGetter) controllerStorage, err := controllerstore.NewStorage(restOptionsGetter)
if err != nil {
return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err
}
serviceRest, serviceRestProxy := servicestore.NewREST(serviceRESTStorage, endpointsStorage, podStorage.Pod, serviceClusterIPAllocator, serviceNodePortAllocator, c.ProxyTransport) serviceRest, serviceRestProxy := servicestore.NewREST(serviceRESTStorage, endpointsStorage, podStorage.Pod, serviceClusterIPAllocator, serviceNodePortAllocator, c.ProxyTransport)

View File

@@ -33,7 +33,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against secrets. // NewREST returns a RESTStorage object that will work against secrets.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.Secret{} }, NewFunc: func() runtime.Object { return &api.Secret{} },
NewListFunc: func() runtime.Object { return &api.SecretList{} }, NewListFunc: func() runtime.Object { return &api.SecretList{} },
@@ -53,7 +53,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
TriggerFunc: map[string]storage.IndexerFunc{"metadata.name": secret.NameTriggerFunc}, TriggerFunc: map[string]storage.IndexerFunc{"metadata.name": secret.NameTriggerFunc},
} }
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -38,7 +38,11 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "secrets", ResourcePrefix: "secrets",
} }
return NewREST(restOptions), server rest, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return rest, server
} }
func validNewSecret(name string) *api.Secret { func validNewSecret(name string) *api.Secret {

View File

@@ -176,12 +176,15 @@ func NewTestRESTWithPods(t *testing.T, endpoints *api.EndpointsList, pods *api.P
serviceStorage := &serviceStorage{} serviceStorage := &serviceStorage{}
podStorage := podstore.NewStorage(generic.RESTOptions{ podStorage, err := podstore.NewStorage(generic.RESTOptions{
StorageConfig: etcdStorage, StorageConfig: etcdStorage,
Decorator: generic.UndecoratedStorage, Decorator: generic.UndecoratedStorage,
DeleteCollectionWorkers: 3, DeleteCollectionWorkers: 3,
ResourcePrefix: "pods", ResourcePrefix: "pods",
}, nil, nil, nil) }, nil, nil, nil)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
if pods != nil && len(pods.Items) > 0 { if pods != nil && len(pods.Items) > 0 {
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
for ix := range pods.Items { for ix := range pods.Items {
@@ -191,11 +194,14 @@ func NewTestRESTWithPods(t *testing.T, endpoints *api.EndpointsList, pods *api.P
} }
} }
} }
endpointStorage := endpointstore.NewREST(generic.RESTOptions{ endpointStorage, err := endpointstore.NewREST(generic.RESTOptions{
StorageConfig: etcdStorage, StorageConfig: etcdStorage,
Decorator: generic.UndecoratedStorage, Decorator: generic.UndecoratedStorage,
ResourcePrefix: "endpoints", ResourcePrefix: "endpoints",
}) })
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
if endpoints != nil && len(endpoints.Items) > 0 { if endpoints != nil && len(endpoints.Items) > 0 {
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
for ix := range endpoints.Items { for ix := range endpoints.Items {

View File

@@ -36,7 +36,7 @@ type GenericREST struct {
} }
// NewREST returns a RESTStorage object that will work against services. // NewREST returns a RESTStorage object that will work against services.
func NewGenericREST(optsGetter generic.RESTOptionsGetter) (*GenericREST, *StatusREST) { func NewGenericREST(optsGetter generic.RESTOptionsGetter) (*GenericREST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.Service{} }, NewFunc: func() runtime.Object { return &api.Service{} },
NewListFunc: func() runtime.Object { return &api.ServiceList{} }, NewListFunc: func() runtime.Object { return &api.ServiceList{} },
@@ -52,12 +52,12 @@ func NewGenericREST(optsGetter generic.RESTOptionsGetter) (*GenericREST, *Status
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = service.StatusStrategy statusStore.UpdateStrategy = service.StatusStrategy
return &GenericREST{store}, &StatusREST{store: &statusStore} return &GenericREST{store}, &StatusREST{store: &statusStore}, nil
} }
var ( var (

View File

@@ -39,7 +39,10 @@ func newStorage(t *testing.T) (*GenericREST, *StatusREST, *etcd3testing.EtcdTest
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "services", ResourcePrefix: "services",
} }
serviceStorage, statusStorage := NewGenericREST(restOptions) serviceStorage, statusStorage, err := NewGenericREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return serviceStorage, statusStorage, server return serviceStorage, statusStorage, server
} }

View File

@@ -38,7 +38,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against service accounts. // NewREST returns a RESTStorage object that will work against service accounts.
func NewREST(optsGetter generic.RESTOptionsGetter, issuer token.TokenGenerator, auds authenticator.Audiences, max time.Duration, podStorage, secretStorage *genericregistry.Store) *REST { func NewREST(optsGetter generic.RESTOptionsGetter, issuer token.TokenGenerator, auds authenticator.Audiences, max time.Duration, podStorage, secretStorage *genericregistry.Store) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &api.ServiceAccount{} }, NewFunc: func() runtime.Object { return &api.ServiceAccount{} },
NewListFunc: func() runtime.Object { return &api.ServiceAccountList{} }, NewListFunc: func() runtime.Object { return &api.ServiceAccountList{} },
@@ -53,7 +53,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter, issuer token.TokenGenerator,
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
var trest *TokenREST var trest *TokenREST
@@ -71,7 +71,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter, issuer token.TokenGenerator,
return &REST{ return &REST{
Store: store, Store: store,
Token: trest, Token: trest,
} }, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -38,7 +38,11 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "serviceaccounts", ResourcePrefix: "serviceaccounts",
} }
return NewREST(restOptions, nil, nil, 0, nil, nil), server rest, err := NewREST(restOptions, nil, nil, 0, nil, nil)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return rest, server
} }
func validNewServiceAccount(name string) *api.ServiceAccount { func validNewServiceAccount(name string) *api.ServiceAccount {

View File

@@ -33,25 +33,32 @@ type RESTStorageProvider struct {
TTL time.Duration TTL time.Duration
} }
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(events.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(events.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(eventsapiv1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(eventsapiv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[eventsapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[eventsapiv1beta1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// events // events
eventsStorage := eventstore.NewREST(restOptionsGetter, uint64(p.TTL.Seconds())) eventsStorage, err := eventstore.NewREST(restOptionsGetter, uint64(p.TTL.Seconds()))
if err != nil {
return storage, err
}
storage["events"] = eventsStorage storage["events"] = eventsStorage
return storage return storage, err
} }
func (p RESTStorageProvider) GroupName() string { func (p RESTStorageProvider) GroupName() string {

View File

@@ -40,14 +40,17 @@ type ContainerStorage struct {
Scale *ScaleREST Scale *ScaleREST
} }
func NewStorage(optsGetter generic.RESTOptionsGetter) ContainerStorage { func NewStorage(optsGetter generic.RESTOptionsGetter) (ContainerStorage, error) {
// scale does not set status, only updates spec so we ignore the status // scale does not set status, only updates spec so we ignore the status
controllerREST, _ := controllerstore.NewREST(optsGetter) controllerREST, _, err := controllerstore.NewREST(optsGetter)
if err != nil {
return ContainerStorage{}, err
}
return ContainerStorage{ return ContainerStorage{
ReplicationController: &RcREST{}, ReplicationController: &RcREST{},
Scale: &ScaleREST{store: controllerREST.Store}, Scale: &ScaleREST{store: controllerREST.Store},
} }, nil
} }
type ScaleREST struct { type ScaleREST struct {

View File

@@ -42,7 +42,11 @@ func newStorage(t *testing.T) (*ScaleREST, *etcd3testing.EtcdTestServer, storage
d() d()
server.Terminate(t) server.Terminate(t)
} }
return NewStorage(restOptions).Scale, server, s, destroyFunc storage, err := NewStorage(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return storage.Scale, server, s, destroyFunc
} }
var validPodTemplate = api.PodTemplate{ var validPodTemplate = api.PodTemplate{

View File

@@ -35,39 +35,52 @@ import (
type RESTStorageProvider struct{} type RESTStorageProvider struct{}
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(extensions.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(extensions.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[extensionsapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[extensionsapiv1beta1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// This is a dummy replication controller for scale subresource purposes. // This is a dummy replication controller for scale subresource purposes.
// TODO: figure out how to enable this only if needed as a part of scale subresource GA. // TODO: figure out how to enable this only if needed as a part of scale subresource GA.
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicationcontrollers")) { if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicationcontrollers")) {
controllerStorage := expcontrollerstore.NewStorage(restOptionsGetter) controllerStorage, err := expcontrollerstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["replicationcontrollers"] = controllerStorage.ReplicationController storage["replicationcontrollers"] = controllerStorage.ReplicationController
storage["replicationcontrollers/scale"] = controllerStorage.Scale storage["replicationcontrollers/scale"] = controllerStorage.Scale
} }
// daemonsets // daemonsets
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets")) { if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets")) {
daemonSetStorage, daemonSetStatusStorage := daemonstore.NewREST(restOptionsGetter) daemonSetStorage, daemonSetStatusStorage, err := daemonstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["daemonsets"] = daemonSetStorage.WithCategories(nil) storage["daemonsets"] = daemonSetStorage.WithCategories(nil)
storage["daemonsets/status"] = daemonSetStatusStorage storage["daemonsets/status"] = daemonSetStatusStorage
} }
//deployments //deployments
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments")) { if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments")) {
deploymentStorage := deploymentstore.NewStorage(restOptionsGetter) deploymentStorage, err := deploymentstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["deployments"] = deploymentStorage.Deployment.WithCategories(nil) storage["deployments"] = deploymentStorage.Deployment.WithCategories(nil)
storage["deployments/status"] = deploymentStorage.Status storage["deployments/status"] = deploymentStorage.Status
storage["deployments/rollback"] = deploymentStorage.Rollback storage["deployments/rollback"] = deploymentStorage.Rollback
@@ -75,20 +88,29 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag
} }
// ingresses // ingresses
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses")) { if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses")) {
ingressStorage, ingressStatusStorage := ingressstore.NewREST(restOptionsGetter) ingressStorage, ingressStatusStorage, err := ingressstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["ingresses"] = ingressStorage storage["ingresses"] = ingressStorage
storage["ingresses/status"] = ingressStatusStorage storage["ingresses/status"] = ingressStatusStorage
} }
// podsecuritypolicy // podsecuritypolicy
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("podsecuritypolicies")) { if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("podsecuritypolicies")) {
podSecurityPolicyStorage := pspstore.NewREST(restOptionsGetter) podSecurityPolicyStorage, err := pspstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["podSecurityPolicies"] = podSecurityPolicyStorage storage["podSecurityPolicies"] = podSecurityPolicyStorage
} }
// replicasets // replicasets
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets")) { if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets")) {
replicaSetStorage := replicasetstore.NewStorage(restOptionsGetter) replicaSetStorage, err := replicasetstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["replicasets"] = replicaSetStorage.ReplicaSet.WithCategories(nil) storage["replicasets"] = replicaSetStorage.ReplicaSet.WithCategories(nil)
storage["replicasets/status"] = replicaSetStorage.Status storage["replicasets/status"] = replicaSetStorage.Status
storage["replicasets/scale"] = replicaSetStorage.Scale storage["replicasets/scale"] = replicaSetStorage.Scale
@@ -96,11 +118,14 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag
// networkpolicies // networkpolicies
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("networkpolicies")) { if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("networkpolicies")) {
networkExtensionsStorage := networkpolicystore.NewREST(restOptionsGetter) networkExtensionsStorage, err := networkpolicystore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["networkpolicies"] = networkExtensionsStorage storage["networkpolicies"] = networkExtensionsStorage
} }
return storage return storage, nil
} }
func (p RESTStorageProvider) GroupName() string { func (p RESTStorageProvider) GroupName() string {

View File

@@ -37,7 +37,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against replication controllers. // NewREST returns a RESTStorage object that will work against replication controllers.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &networking.Ingress{} }, NewFunc: func() runtime.Object { return &networking.Ingress{} },
NewListFunc: func() runtime.Object { return &networking.IngressList{} }, NewListFunc: func() runtime.Object { return &networking.IngressList{} },
@@ -51,12 +51,12 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = ingress.StatusStrategy statusStore.UpdateStrategy = ingress.StatusStrategy
return &REST{store}, &StatusREST{store: &statusStore} return &REST{store}, &StatusREST{store: &statusStore}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -40,7 +40,10 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer)
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "ingresses", ResourcePrefix: "ingresses",
} }
ingressStorage, statusStorage := NewREST(restOptions) ingressStorage, statusStorage, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return ingressStorage, statusStorage, server return ingressStorage, statusStorage, server
} }

View File

@@ -34,7 +34,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against NetworkPolicies // NewREST returns a RESTStorage object that will work against NetworkPolicies
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &networkingapi.NetworkPolicy{} }, NewFunc: func() runtime.Object { return &networkingapi.NetworkPolicy{} },
NewListFunc: func() runtime.Object { return &networkingapi.NetworkPolicyList{} }, NewListFunc: func() runtime.Object { return &networkingapi.NetworkPolicyList{} },
@@ -48,10 +48,10 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -40,7 +40,11 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "networkpolicies", ResourcePrefix: "networkpolicies",
} }
return NewREST(restOptions), server rest, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return rest, server
} }
func validNetworkPolicy() *networking.NetworkPolicy { func validNetworkPolicy() *networking.NetworkPolicy {

View File

@@ -31,38 +31,52 @@ import (
type RESTStorageProvider struct{} type RESTStorageProvider struct{}
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(networking.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(networking.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(networkingapiv1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(networkingapiv1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[networkingapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[networkingapiv1.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(networkingapiv1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(networkingapiv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[networkingapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[networkingapiv1beta1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// networkpolicies // networkpolicies
networkPolicyStorage := networkpolicystore.NewREST(restOptionsGetter) networkPolicyStorage, err := networkpolicystore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["networkpolicies"] = networkPolicyStorage storage["networkpolicies"] = networkPolicyStorage
return storage return storage, nil
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// ingresses // ingresses
ingressStorage, ingressStatusStorage := ingressstore.NewREST(restOptionsGetter) ingressStorage, ingressStatusStorage, err := ingressstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["ingresses"] = ingressStorage storage["ingresses"] = ingressStorage
storage["ingresses/status"] = ingressStatusStorage storage["ingresses/status"] = ingressStatusStorage
return storage return storage, nil
} }
func (p RESTStorageProvider) GroupName() string { func (p RESTStorageProvider) GroupName() string {

View File

@@ -32,34 +32,48 @@ import (
type RESTStorageProvider struct{} type RESTStorageProvider struct{}
// NewRESTStorage returns a RESTStorageProvider // NewRESTStorage returns a RESTStorageProvider
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(nodeinternal.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(nodeinternal.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
if apiResourceConfigSource.VersionEnabled(nodev1alpha1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(nodev1alpha1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[nodev1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[nodev1alpha1.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(nodev1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(nodev1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[nodev1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[nodev1beta1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
s := runtimeclassstorage.NewREST(restOptionsGetter) s, err := runtimeclassstorage.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["runtimeclasses"] = s storage["runtimeclasses"] = s
return storage return storage, err
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
s := runtimeclassstorage.NewREST(restOptionsGetter) s, err := runtimeclassstorage.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["runtimeclasses"] = s storage["runtimeclasses"] = s
return storage return storage, err
} }
// GroupName is the group name for the storage provider // GroupName is the group name for the storage provider

View File

@@ -30,7 +30,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against runtime classes. // NewREST returns a RESTStorage object that will work against runtime classes.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &node.RuntimeClass{} }, NewFunc: func() runtime.Object { return &node.RuntimeClass{} },
NewListFunc: func() runtime.Object { return &node.RuntimeClassList{} }, NewListFunc: func() runtime.Object { return &node.RuntimeClassList{} },
@@ -45,7 +45,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -37,7 +37,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against pod disruption budgets. // NewREST returns a RESTStorage object that will work against pod disruption budgets.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &policyapi.PodDisruptionBudget{} }, NewFunc: func() runtime.Object { return &policyapi.PodDisruptionBudget{} },
NewListFunc: func() runtime.Object { return &policyapi.PodDisruptionBudgetList{} }, NewListFunc: func() runtime.Object { return &policyapi.PodDisruptionBudgetList{} },
@@ -51,12 +51,12 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST) {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, nil, err
} }
statusStore := *store statusStore := *store
statusStore.UpdateStrategy = poddisruptionbudget.StatusStrategy statusStore.UpdateStrategy = poddisruptionbudget.StatusStrategy
return &REST{store}, &StatusREST{store: &statusStore} return &REST{store}, &StatusREST{store: &statusStore}, nil
} }
// ShortNames implements the ShortNamesProvider interface. Returns a list of short names for a resource. // ShortNames implements the ShortNamesProvider interface. Returns a list of short names for a resource.

View File

@@ -35,7 +35,10 @@ import (
func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer) { func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer) {
etcdStorage, server := registrytest.NewEtcdStorage(t, policy.GroupName) etcdStorage, server := registrytest.NewEtcdStorage(t, policy.GroupName)
restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "poddisruptionbudgets"} restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "poddisruptionbudgets"}
podDisruptionBudgetStorage, statusStorage := NewREST(restOptions) podDisruptionBudgetStorage, statusStorage, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return podDisruptionBudgetStorage, statusStorage, server return podDisruptionBudgetStorage, statusStorage, server
} }

View File

@@ -33,7 +33,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against PodSecurityPolicy objects. // NewREST returns a RESTStorage object that will work against PodSecurityPolicy objects.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &policy.PodSecurityPolicy{} }, NewFunc: func() runtime.Object { return &policy.PodSecurityPolicy{} },
NewListFunc: func() runtime.Object { return &policy.PodSecurityPolicyList{} }, NewListFunc: func() runtime.Object { return &policy.PodSecurityPolicyList{} },
@@ -48,9 +48,9 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }
// ShortNames implements the ShortNamesProvider interface. Returns a list of short names for a resource. // ShortNames implements the ShortNamesProvider interface. Returns a list of short names for a resource.

View File

@@ -40,7 +40,11 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "podsecuritypolicies", ResourcePrefix: "podsecuritypolicies",
} }
return NewREST(restOptions), server rest, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return rest, server
} }
func validNewPodSecurityPolicy() *policy.PodSecurityPolicy { func validNewPodSecurityPolicy() *policy.PodSecurityPolicy {

View File

@@ -30,27 +30,38 @@ import (
type RESTStorageProvider struct{} type RESTStorageProvider struct{}
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(policy.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(policy.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(policyapiv1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(policyapiv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[policyapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[policyapiv1beta1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// poddisruptionbudgets // poddisruptionbudgets
poddisruptionbudgetStorage, poddisruptionbudgetStatusStorage := poddisruptionbudgetstore.NewREST(restOptionsGetter) poddisruptionbudgetStorage, poddisruptionbudgetStatusStorage, err := poddisruptionbudgetstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["poddisruptionbudgets"] = poddisruptionbudgetStorage storage["poddisruptionbudgets"] = poddisruptionbudgetStorage
storage["poddisruptionbudgets/status"] = poddisruptionbudgetStatusStorage storage["poddisruptionbudgets/status"] = poddisruptionbudgetStatusStorage
storage["podsecuritypolicies"] = pspstore.NewREST(restOptionsGetter) rest, err := pspstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["podsecuritypolicies"] = rest
return storage return storage, err
} }
func (p RESTStorageProvider) GroupName() string { func (p RESTStorageProvider) GroupName() string {

View File

@@ -30,7 +30,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against ClusterRole objects. // NewREST returns a RESTStorage object that will work against ClusterRole objects.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &rbac.ClusterRole{} }, NewFunc: func() runtime.Object { return &rbac.ClusterRole{} },
NewListFunc: func() runtime.Object { return &rbac.ClusterRoleList{} }, NewListFunc: func() runtime.Object { return &rbac.ClusterRoleList{} },
@@ -42,8 +42,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -33,7 +33,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against ClusterRoleBinding objects. // NewREST returns a RESTStorage object that will work against ClusterRoleBinding objects.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &rbac.ClusterRoleBinding{} }, NewFunc: func() runtime.Object { return &rbac.ClusterRoleBinding{} },
NewListFunc: func() runtime.Object { return &rbac.ClusterRoleBindingList{} }, NewListFunc: func() runtime.Object { return &rbac.ClusterRoleBindingList{} },
@@ -47,8 +47,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -65,30 +65,54 @@ type RESTStorageProvider struct {
var _ genericapiserver.PostStartHookProvider = RESTStorageProvider{} var _ genericapiserver.PostStartHookProvider = RESTStorageProvider{}
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(rbac.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(rbac.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(rbacapiv1alpha1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(rbacapiv1alpha1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[rbacapiv1alpha1.SchemeGroupVersion.Version] = p.storage(rbacapiv1alpha1.SchemeGroupVersion, apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.storage(rbacapiv1alpha1.SchemeGroupVersion, apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[rbacapiv1alpha1.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(rbacapiv1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(rbacapiv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[rbacapiv1beta1.SchemeGroupVersion.Version] = p.storage(rbacapiv1beta1.SchemeGroupVersion, apiResourceConfigSource, restOptionsGetter) if stoageMap, err := p.storage(rbacapiv1beta1.SchemeGroupVersion, apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[rbacapiv1beta1.SchemeGroupVersion.Version] = stoageMap
}
} }
if apiResourceConfigSource.VersionEnabled(rbacapiv1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(rbacapiv1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[rbacapiv1.SchemeGroupVersion.Version] = p.storage(rbacapiv1.SchemeGroupVersion, apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.storage(rbacapiv1.SchemeGroupVersion, apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[rbacapiv1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) storage(version schema.GroupVersion, apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) storage(version schema.GroupVersion, apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
rolesStorage := rolestore.NewREST(restOptionsGetter) rolesStorage, err := rolestore.NewREST(restOptionsGetter)
roleBindingsStorage := rolebindingstore.NewREST(restOptionsGetter) if err != nil {
clusterRolesStorage := clusterrolestore.NewREST(restOptionsGetter) return storage, err
clusterRoleBindingsStorage := clusterrolebindingstore.NewREST(restOptionsGetter) }
roleBindingsStorage, err := rolebindingstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
clusterRolesStorage, err := clusterrolestore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
clusterRoleBindingsStorage, err := clusterrolebindingstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
authorizationRuleResolver := rbacregistryvalidation.NewDefaultRuleResolver( authorizationRuleResolver := rbacregistryvalidation.NewDefaultRuleResolver(
role.AuthorizerAdapter{Registry: role.NewRegistry(rolesStorage)}, role.AuthorizerAdapter{Registry: role.NewRegistry(rolesStorage)},
@@ -109,7 +133,7 @@ func (p RESTStorageProvider) storage(version schema.GroupVersion, apiResourceCon
// clusterrolebindings // clusterrolebindings
storage["clusterrolebindings"] = clusterrolebindingpolicybased.NewStorage(clusterRoleBindingsStorage, p.Authorizer, authorizationRuleResolver) storage["clusterrolebindings"] = clusterrolebindingpolicybased.NewStorage(clusterRoleBindingsStorage, p.Authorizer, authorizationRuleResolver)
return storage return storage, nil
} }
func (p RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStartHookFunc, error) { func (p RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStartHookFunc, error) {

View File

@@ -30,7 +30,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against Role objects. // NewREST returns a RESTStorage object that will work against Role objects.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &rbac.Role{} }, NewFunc: func() runtime.Object { return &rbac.Role{} },
NewListFunc: func() runtime.Object { return &rbac.RoleList{} }, NewListFunc: func() runtime.Object { return &rbac.RoleList{} },
@@ -42,8 +42,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -33,7 +33,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against RoleBinding objects. // NewREST returns a RESTStorage object that will work against RoleBinding objects.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &rbac.RoleBinding{} }, NewFunc: func() runtime.Object { return &rbac.RoleBinding{} },
NewListFunc: func() runtime.Object { return &rbac.RoleBindingList{} }, NewListFunc: func() runtime.Object { return &rbac.RoleBindingList{} },
@@ -47,8 +47,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -19,7 +19,6 @@ package storage
import ( import (
"context" "context"
"errors" "errors"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@@ -39,7 +38,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against priority classes. // NewREST returns a RESTStorage object that will work against priority classes.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &scheduling.PriorityClass{} }, NewFunc: func() runtime.Object { return &scheduling.PriorityClass{} },
NewListFunc: func() runtime.Object { return &scheduling.PriorityClassList{} }, NewListFunc: func() runtime.Object { return &scheduling.PriorityClassList{} },
@@ -53,10 +52,10 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -40,7 +40,11 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "priorityclasses", ResourcePrefix: "priorityclasses",
} }
return NewREST(restOptions), server rest, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unable to create REST %v", err)
}
return rest, server
} }
func validNewPriorityClass() *scheduling.PriorityClass { func validNewPriorityClass() *scheduling.PriorityClass {

View File

@@ -46,46 +46,66 @@ type RESTStorageProvider struct{}
var _ genericapiserver.PostStartHookProvider = RESTStorageProvider{} var _ genericapiserver.PostStartHookProvider = RESTStorageProvider{}
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(scheduling.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(scheduling.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
if apiResourceConfigSource.VersionEnabled(schedulingapiv1alpha1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(schedulingapiv1alpha1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[schedulingapiv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) if storage, err := p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[schedulingapiv1alpha1.SchemeGroupVersion.Version] = storage
}
} }
if apiResourceConfigSource.VersionEnabled(schedulingapiv1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(schedulingapiv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[schedulingapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) if storage, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[schedulingapiv1beta1.SchemeGroupVersion.Version] = storage
}
} }
if apiResourceConfigSource.VersionEnabled(schedulingapiv1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(schedulingapiv1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[schedulingapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) if storage, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[schedulingapiv1.SchemeGroupVersion.Version] = storage
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// priorityclasses // priorityclasses
priorityClassStorage := priorityclassstore.NewREST(restOptionsGetter) if priorityClassStorage, err := priorityclassstore.NewREST(restOptionsGetter); err != nil {
storage["priorityclasses"] = priorityClassStorage return nil, err
} else {
return storage storage["priorityclasses"] = priorityClassStorage
}
return storage, nil
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// priorityclasses // priorityclasses
priorityClassStorage := priorityclassstore.NewREST(restOptionsGetter) if priorityClassStorage, err := priorityclassstore.NewREST(restOptionsGetter); err != nil {
storage["priorityclasses"] = priorityClassStorage return nil, err
} else {
storage["priorityclasses"] = priorityClassStorage
}
return storage return storage, nil
} }
func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// priorityclasses // priorityclasses
priorityClassStorage := priorityclassstore.NewREST(restOptionsGetter) if priorityClassStorage, err := priorityclassstore.NewREST(restOptionsGetter); err != nil {
storage["priorityclasses"] = priorityClassStorage return nil, err
} else {
storage["priorityclasses"] = priorityClassStorage
}
return storage return storage, nil
} }
func (p RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStartHookFunc, error) { func (p RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStartHookFunc, error) {

View File

@@ -30,7 +30,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against replication controllers. // NewREST returns a RESTStorage object that will work against replication controllers.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &settingsapi.PodPreset{} }, NewFunc: func() runtime.Object { return &settingsapi.PodPreset{} },
NewListFunc: func() runtime.Object { return &settingsapi.PodPresetList{} }, NewListFunc: func() runtime.Object { return &settingsapi.PodPresetList{} },
@@ -42,8 +42,8 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }

View File

@@ -39,7 +39,11 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "podpresets", ResourcePrefix: "podpresets",
} }
return NewREST(restOptions), server rest, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return rest, server
} }
func validNewPodPreset(namespace string) *settings.PodPreset { func validNewPodPreset(namespace string) *settings.PodPreset {

View File

@@ -29,25 +29,32 @@ import (
type RESTStorageProvider struct{} type RESTStorageProvider struct{}
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(settings.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(settings.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(settingsapiv1alpha1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(settingsapiv1alpha1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[settingsapiv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, nil
} else {
apiGroupInfo.VersionedResourcesStorageMap[settingsapiv1alpha1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// podpresets // podpresets
podPresetStorage := podpresetstore.NewREST(restOptionsGetter) podPresetStorage, err := podpresetstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["podpresets"] = podPresetStorage storage["podpresets"] = podPresetStorage
return storage return storage, err
} }
func (p RESTStorageProvider) GroupName() string { func (p RESTStorageProvider) GroupName() string {

View File

@@ -35,7 +35,7 @@ type REST struct {
} }
// NewStorage returns a RESTStorage object that will work against CSIDrivers // NewStorage returns a RESTStorage object that will work against CSIDrivers
func NewStorage(optsGetter generic.RESTOptionsGetter) *CSIDriverStorage { func NewStorage(optsGetter generic.RESTOptionsGetter) (*CSIDriverStorage, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &storageapi.CSIDriver{} }, NewFunc: func() runtime.Object { return &storageapi.CSIDriver{} },
NewListFunc: func() runtime.Object { return &storageapi.CSIDriverList{} }, NewListFunc: func() runtime.Object { return &storageapi.CSIDriverList{} },
@@ -48,10 +48,10 @@ func NewStorage(optsGetter generic.RESTOptionsGetter) *CSIDriverStorage {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &CSIDriverStorage{ return &CSIDriverStorage{
CSIDriver: &REST{store}, CSIDriver: &REST{store},
} }, nil
} }

View File

@@ -38,7 +38,10 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "csidrivers", ResourcePrefix: "csidrivers",
} }
csiDriverStorage := NewStorage(restOptions) csiDriverStorage, err := NewStorage(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return csiDriverStorage.CSIDriver, server return csiDriverStorage.CSIDriver, server
} }

View File

@@ -35,7 +35,7 @@ type REST struct {
} }
// NewStorage returns a RESTStorage object that will work against CSINodes // NewStorage returns a RESTStorage object that will work against CSINodes
func NewStorage(optsGetter generic.RESTOptionsGetter) *CSINodeStorage { func NewStorage(optsGetter generic.RESTOptionsGetter) (*CSINodeStorage, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &storageapi.CSINode{} }, NewFunc: func() runtime.Object { return &storageapi.CSINode{} },
NewListFunc: func() runtime.Object { return &storageapi.CSINodeList{} }, NewListFunc: func() runtime.Object { return &storageapi.CSINodeList{} },
@@ -48,10 +48,10 @@ func NewStorage(optsGetter generic.RESTOptionsGetter) *CSINodeStorage {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &CSINodeStorage{ return &CSINodeStorage{
CSINode: &REST{store}, CSINode: &REST{store},
} }, nil
} }

View File

@@ -38,7 +38,10 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "csinodes", ResourcePrefix: "csinodes",
} }
csiNodeStorage := NewStorage(restOptions) csiNodeStorage, err := NewStorage(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return csiNodeStorage.CSINode, server return csiNodeStorage.CSINode, server
} }

View File

@@ -37,61 +37,94 @@ import (
type RESTStorageProvider struct { type RESTStorageProvider struct {
} }
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(storageapi.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(storageapi.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
// TODO refactor the plumbing to provide the information in the APIGroupInfo // TODO refactor the plumbing to provide the information in the APIGroupInfo
if apiResourceConfigSource.VersionEnabled(storageapiv1alpha1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(storageapiv1alpha1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[storageapiv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[storageapiv1alpha1.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(storageapiv1beta1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(storageapiv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[storageapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[storageapiv1beta1.SchemeGroupVersion.Version] = storageMap
}
} }
if apiResourceConfigSource.VersionEnabled(storageapiv1.SchemeGroupVersion) { if apiResourceConfigSource.VersionEnabled(storageapiv1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[storageapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, false, err
} else {
apiGroupInfo.VersionedResourcesStorageMap[storageapiv1.SchemeGroupVersion.Version] = storageMap
}
} }
return apiGroupInfo, true return apiGroupInfo, true, nil
} }
func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// volumeattachments // volumeattachments
volumeAttachmentStorage := volumeattachmentstore.NewStorage(restOptionsGetter) volumeAttachmentStorage, err := volumeattachmentstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["volumeattachments"] = volumeAttachmentStorage.VolumeAttachment storage["volumeattachments"] = volumeAttachmentStorage.VolumeAttachment
return storage return storage, nil
} }
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
// storageclasses // storageclasses
storageClassStorage := storageclassstore.NewREST(restOptionsGetter) storageClassStorage, err := storageclassstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage["storageclasses"] = storageClassStorage storage["storageclasses"] = storageClassStorage
// volumeattachments // volumeattachments
volumeAttachmentStorage := volumeattachmentstore.NewStorage(restOptionsGetter) volumeAttachmentStorage, err := volumeattachmentstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["volumeattachments"] = volumeAttachmentStorage.VolumeAttachment storage["volumeattachments"] = volumeAttachmentStorage.VolumeAttachment
// register csinodes if CSINodeInfo feature gate is enabled // register csinodes if CSINodeInfo feature gate is enabled
if utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) { if utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) {
csiNodeStorage := csinodestore.NewStorage(restOptionsGetter) csiNodeStorage, err := csinodestore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["csinodes"] = csiNodeStorage.CSINode storage["csinodes"] = csiNodeStorage.CSINode
} }
// register csidrivers if CSIDriverRegistry feature gate is enabled // register csidrivers if CSIDriverRegistry feature gate is enabled
if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) { if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) {
csiDriverStorage := csidriverstore.NewStorage(restOptionsGetter) csiDriverStorage, err := csidriverstore.NewStorage(restOptionsGetter)
if err != nil {
return storage, err
}
storage["csidrivers"] = csiDriverStorage.CSIDriver storage["csidrivers"] = csiDriverStorage.CSIDriver
} }
return storage return storage, nil
} }
func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storageClassStorage := storageclassstore.NewREST(restOptionsGetter) storageClassStorage, err := storageclassstore.NewREST(restOptionsGetter)
volumeAttachmentStorage := volumeattachmentstore.NewStorage(restOptionsGetter) if err != nil {
return nil, err
}
volumeAttachmentStorage, err := volumeattachmentstore.NewStorage(restOptionsGetter)
if err != nil {
return nil, err
}
storage := map[string]rest.Storage{ storage := map[string]rest.Storage{
// storageclasses // storageclasses
@@ -102,7 +135,7 @@ func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.API
"volumeattachments/status": volumeAttachmentStorage.Status, "volumeattachments/status": volumeAttachmentStorage.Status,
} }
return storage return storage, nil
} }
func (p RESTStorageProvider) GroupName() string { func (p RESTStorageProvider) GroupName() string {

View File

@@ -33,7 +33,7 @@ type REST struct {
} }
// NewREST returns a RESTStorage object that will work against persistent volumes. // NewREST returns a RESTStorage object that will work against persistent volumes.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST { func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &storageapi.StorageClass{} }, NewFunc: func() runtime.Object { return &storageapi.StorageClass{} },
NewListFunc: func() runtime.Object { return &storageapi.StorageClassList{} }, NewListFunc: func() runtime.Object { return &storageapi.StorageClassList{} },
@@ -48,10 +48,10 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
return &REST{store} return &REST{store}, nil
} }
// Implement ShortNamesProvider // Implement ShortNamesProvider

View File

@@ -39,7 +39,10 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "storageclasses", ResourcePrefix: "storageclasses",
} }
storageClassStorage := NewREST(restOptions) storageClassStorage, err := NewREST(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return storageClassStorage, server return storageClassStorage, server
} }

View File

@@ -43,7 +43,7 @@ type REST struct {
} }
// NewStorage returns a RESTStorage object that will work against VolumeAttachments // NewStorage returns a RESTStorage object that will work against VolumeAttachments
func NewStorage(optsGetter generic.RESTOptionsGetter) *VolumeAttachmentStorage { func NewStorage(optsGetter generic.RESTOptionsGetter) (*VolumeAttachmentStorage, error) {
store := &genericregistry.Store{ store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &storageapi.VolumeAttachment{} }, NewFunc: func() runtime.Object { return &storageapi.VolumeAttachment{} },
NewListFunc: func() runtime.Object { return &storageapi.VolumeAttachmentList{} }, NewListFunc: func() runtime.Object { return &storageapi.VolumeAttachmentList{} },
@@ -58,7 +58,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter) *VolumeAttachmentStorage {
} }
options := &generic.StoreOptions{RESTOptions: optsGetter} options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up return nil, err
} }
statusStore := *store statusStore := *store
@@ -67,7 +67,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter) *VolumeAttachmentStorage {
return &VolumeAttachmentStorage{ return &VolumeAttachmentStorage{
VolumeAttachment: &REST{store}, VolumeAttachment: &REST{store},
Status: &StatusREST{store: &statusStore}, Status: &StatusREST{store: &statusStore},
} }, nil
} }
// StatusREST implements the REST endpoint for changing the status of a VolumeAttachment // StatusREST implements the REST endpoint for changing the status of a VolumeAttachment

View File

@@ -42,7 +42,10 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer)
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
ResourcePrefix: "volumeattachments", ResourcePrefix: "volumeattachments",
} }
volumeAttachmentStorage := NewStorage(restOptions) volumeAttachmentStorage, err := NewStorage(restOptions)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
return volumeAttachmentStorage.VolumeAttachment, volumeAttachmentStorage.Status, server return volumeAttachmentStorage.VolumeAttachment, volumeAttachmentStorage.Status, server
} }

View File

@@ -97,12 +97,28 @@ func (getter *testRESTOptionsGetter) GetRESTOptions(resource schema.GroupResourc
return generic.RESTOptions{StorageConfig: storageConfig, Decorator: generic.UndecoratedStorage, ResourcePrefix: resource.Resource}, nil return generic.RESTOptions{StorageConfig: storageConfig, Decorator: generic.UndecoratedStorage, ResourcePrefix: resource.Resource}, nil
} }
func newRBACAuthorizer(config *master.Config) authorizer.Authorizer { func newRBACAuthorizer(t *testing.T, config *master.Config) authorizer.Authorizer {
optsGetter := &testRESTOptionsGetter{config} optsGetter := &testRESTOptionsGetter{config}
roleRegistry := role.AuthorizerAdapter{Registry: role.NewRegistry(rolestore.NewREST(optsGetter))} roleRest, err := rolestore.NewREST(optsGetter)
roleBindingRegistry := rolebinding.AuthorizerAdapter{Registry: rolebinding.NewRegistry(rolebindingstore.NewREST(optsGetter))} if err != nil {
clusterRoleRegistry := clusterrole.AuthorizerAdapter{Registry: clusterrole.NewRegistry(clusterrolestore.NewREST(optsGetter))} t.Fatalf("unexpected error from REST storage: %v", err)
clusterRoleBindingRegistry := clusterrolebinding.AuthorizerAdapter{Registry: clusterrolebinding.NewRegistry(clusterrolebindingstore.NewREST(optsGetter))} }
roleRegistry := role.AuthorizerAdapter{Registry: role.NewRegistry(roleRest)}
rolebindingRest, err := rolebindingstore.NewREST(optsGetter)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
roleBindingRegistry := rolebinding.AuthorizerAdapter{Registry: rolebinding.NewRegistry(rolebindingRest)}
clusterroleRest, err := clusterrolestore.NewREST(optsGetter)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
clusterRoleRegistry := clusterrole.AuthorizerAdapter{Registry: clusterrole.NewRegistry(clusterroleRest)}
clusterrolebindingRest, err := clusterrolebindingstore.NewREST(optsGetter)
if err != nil {
t.Fatalf("unexpected error from REST storage: %v", err)
}
clusterRoleBindingRegistry := clusterrolebinding.AuthorizerAdapter{Registry: clusterrolebinding.NewRegistry(clusterrolebindingRest)}
return rbac.New(roleRegistry, roleBindingRegistry, clusterRoleRegistry, clusterRoleBindingRegistry) return rbac.New(roleRegistry, roleBindingRegistry, clusterRoleRegistry, clusterRoleBindingRegistry)
} }
@@ -515,7 +531,7 @@ func TestRBAC(t *testing.T) {
for i, tc := range tests { for i, tc := range tests {
// Create an API Server. // Create an API Server.
masterConfig := framework.NewIntegrationTestMasterConfig() masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.GenericConfig.Authorization.Authorizer = newRBACAuthorizer(masterConfig) masterConfig.GenericConfig.Authorization.Authorizer = newRBACAuthorizer(t, masterConfig)
masterConfig.GenericConfig.Authentication.Authenticator = bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{ masterConfig.GenericConfig.Authentication.Authenticator = bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{
superUser: {Name: "admin", Groups: []string{"system:masters"}}, superUser: {Name: "admin", Groups: []string{"system:masters"}},
"any-rolebinding-writer": {Name: "any-rolebinding-writer"}, "any-rolebinding-writer": {Name: "any-rolebinding-writer"},
@@ -629,7 +645,7 @@ func TestBootstrapping(t *testing.T) {
superUser := "admin/system:masters" superUser := "admin/system:masters"
masterConfig := framework.NewIntegrationTestMasterConfig() masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.GenericConfig.Authorization.Authorizer = newRBACAuthorizer(masterConfig) masterConfig.GenericConfig.Authorization.Authorizer = newRBACAuthorizer(t, masterConfig)
masterConfig.GenericConfig.Authentication.Authenticator = bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{ masterConfig.GenericConfig.Authentication.Authenticator = bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{
superUser: {Name: "admin", Groups: []string{"system:masters"}}, superUser: {Name: "admin", Groups: []string{"system:masters"}},
})) }))
@@ -690,7 +706,7 @@ func TestDiscoveryUpgradeBootstrapping(t *testing.T) {
superUser := "admin/system:masters" superUser := "admin/system:masters"
masterConfig := framework.NewIntegrationTestMasterConfig() masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.GenericConfig.Authorization.Authorizer = newRBACAuthorizer(masterConfig) masterConfig.GenericConfig.Authorization.Authorizer = newRBACAuthorizer(t, masterConfig)
masterConfig.GenericConfig.Authentication.Authenticator = bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{ masterConfig.GenericConfig.Authentication.Authenticator = bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{
superUser: {Name: "admin", Groups: []string{"system:masters"}}, superUser: {Name: "admin", Groups: []string{"system:masters"}},
})) }))