From 17a21c7bdbd2342a2d2b1d3e3cd530c5dc47d9b8 Mon Sep 17 00:00:00 2001 From: deads2k Date: Fri, 23 Sep 2016 15:10:47 -0400 Subject: [PATCH 1/2] move reststorage providers to their correct packages --- pkg/master/master.go | 66 +++++---- pkg/master/master_test.go | 3 +- pkg/master/thirdparty_controller.go | 111 --------------- .../apps/rest}/storage_apps.go | 10 +- .../rest}/storage_authentication.go | 10 +- .../rest}/storage_authorization.go | 10 +- .../autoscaling/rest}/storage_autoscaling.go | 10 +- .../batch/rest}/storage_batch.go | 12 +- .../rest}/storage_certificates.go | 10 +- .../extensions/rest}/storage_extensions.go | 12 +- .../extensions/rest/thirdparty_controller.go | 131 ++++++++++++++++++ .../rest}/thirdparty_controller_test.go | 6 +- .../policy/rest}/storage_policy.go | 10 +- .../rbac/{storage => rest}/storage_rbac.go | 2 +- .../storage/rest}/storage_storage.go | 10 +- 15 files changed, 224 insertions(+), 189 deletions(-) rename pkg/{master => registry/apps/rest}/storage_apps.go (75%) rename pkg/{master => registry/authentication/rest}/storage_authentication.go (77%) rename pkg/{master => registry/authorization/rest}/storage_authorization.go (80%) rename pkg/{master => registry/autoscaling/rest}/storage_autoscaling.go (76%) rename pkg/{master => registry/batch/rest}/storage_batch.go (80%) rename pkg/{master => registry/certificates/rest}/storage_certificates.go (77%) rename pkg/{master => registry/extensions/rest}/storage_extensions.go (90%) create mode 100644 pkg/registry/extensions/rest/thirdparty_controller.go rename pkg/{master => registry/extensions/rest}/thirdparty_controller_test.go (97%) rename pkg/{master => registry/policy/rest}/storage_policy.go (76%) rename pkg/registry/rbac/{storage => rest}/storage_rbac.go (99%) rename pkg/{master => registry/storage/rest}/storage_storage.go (75%) diff --git a/pkg/master/master.go b/pkg/master/master.go index aaafe8920ee..6a3cd75c69d 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -55,6 +55,31 @@ import ( "k8s.io/kubernetes/pkg/healthz" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/master/ports" + + "k8s.io/kubernetes/pkg/registry/generic" + "k8s.io/kubernetes/pkg/registry/generic/registry" + "k8s.io/kubernetes/pkg/routes" + "k8s.io/kubernetes/pkg/runtime" + etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util" + "k8s.io/kubernetes/pkg/storage/storagebackend" + "k8s.io/kubernetes/pkg/util/sets" + + "github.com/golang/glog" + "github.com/prometheus/client_golang/prometheus" + + // RESTStorage installers + appsrest "k8s.io/kubernetes/pkg/registry/apps/rest" + authenticationrest "k8s.io/kubernetes/pkg/registry/authentication/rest" + authorizationrest "k8s.io/kubernetes/pkg/registry/authorization/rest" + autoscalingrest "k8s.io/kubernetes/pkg/registry/autoscaling/rest" + batchrest "k8s.io/kubernetes/pkg/registry/batch/rest" + certificatesrest "k8s.io/kubernetes/pkg/registry/certificates/rest" + extensionsrest "k8s.io/kubernetes/pkg/registry/extensions/rest" + policyrest "k8s.io/kubernetes/pkg/registry/policy/rest" + rbacrest "k8s.io/kubernetes/pkg/registry/rbac/rest" + storagerest "k8s.io/kubernetes/pkg/registry/storage/rest" + + // direct etcd registry dependencies controlleretcd "k8s.io/kubernetes/pkg/registry/controller/etcd" "k8s.io/kubernetes/pkg/registry/core/componentstatus" configmapetcd "k8s.io/kubernetes/pkg/registry/core/configmap/etcd" @@ -82,17 +107,6 @@ import ( serviceaccountetcd "k8s.io/kubernetes/pkg/registry/core/serviceaccount/etcd" "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata" thirdpartyresourcedataetcd "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata/etcd" - "k8s.io/kubernetes/pkg/registry/generic" - "k8s.io/kubernetes/pkg/registry/generic/registry" - rbacstorage "k8s.io/kubernetes/pkg/registry/rbac/storage" - "k8s.io/kubernetes/pkg/routes" - "k8s.io/kubernetes/pkg/runtime" - etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util" - "k8s.io/kubernetes/pkg/storage/storagebackend" - "k8s.io/kubernetes/pkg/util/sets" - - "github.com/golang/glog" - "github.com/prometheus/client_golang/prometheus" ) const ( @@ -224,19 +238,19 @@ func New(c *Config) (*Master, error) { if c.RESTStorageProviders == nil { c.RESTStorageProviders = map[string]genericapiserver.RESTStorageProvider{} } - c.RESTStorageProviders[appsapi.GroupName] = AppsRESTStorageProvider{} - c.RESTStorageProviders[autoscaling.GroupName] = AutoscalingRESTStorageProvider{} - c.RESTStorageProviders[batch.GroupName] = BatchRESTStorageProvider{} - c.RESTStorageProviders[certificates.GroupName] = CertificatesRESTStorageProvider{} - c.RESTStorageProviders[extensions.GroupName] = ExtensionsRESTStorageProvider{ + c.RESTStorageProviders[appsapi.GroupName] = appsrest.RESTStorageProvider{} + c.RESTStorageProviders[authenticationv1beta1.GroupName] = authenticationrest.RESTStorageProvider{Authenticator: c.Authenticator} + c.RESTStorageProviders[authorization.GroupName] = authorizationrest.RESTStorageProvider{Authorizer: c.Authorizer} + c.RESTStorageProviders[autoscaling.GroupName] = autoscalingrest.RESTStorageProvider{} + c.RESTStorageProviders[batch.GroupName] = batchrest.RESTStorageProvider{} + c.RESTStorageProviders[certificates.GroupName] = certificatesrest.RESTStorageProvider{} + c.RESTStorageProviders[extensions.GroupName] = extensionsrest.RESTStorageProvider{ ResourceInterface: m, DisableThirdPartyControllerForTesting: m.disableThirdPartyControllerForTesting, } - c.RESTStorageProviders[policy.GroupName] = PolicyRESTStorageProvider{} - c.RESTStorageProviders[rbac.GroupName] = &rbacstorage.RESTStorageProvider{AuthorizerRBACSuperUser: c.AuthorizerRBACSuperUser} - c.RESTStorageProviders[storage.GroupName] = StorageRESTStorageProvider{} - c.RESTStorageProviders[authenticationv1beta1.GroupName] = AuthenticationRESTStorageProvider{Authenticator: c.Authenticator} - c.RESTStorageProviders[authorization.GroupName] = AuthorizationRESTStorageProvider{Authorizer: c.Authorizer} + c.RESTStorageProviders[policy.GroupName] = policyrest.RESTStorageProvider{} + c.RESTStorageProviders[rbac.GroupName] = &rbacrest.RESTStorageProvider{AuthorizerRBACSuperUser: c.AuthorizerRBACSuperUser} + c.RESTStorageProviders[storage.GroupName] = storagerest.RESTStorageProvider{} m.InstallAPIs(c) // TODO: Attempt clean shutdown? @@ -566,7 +580,7 @@ func (m *Master) HasThirdPartyResource(rsrc *extensions.ThirdPartyResource) (boo if err != nil { return false, err } - path := makeThirdPartyPath(group) + path := extensionsrest.MakeThirdPartyPath(group) m.thirdPartyResourcesLock.Lock() defer m.thirdPartyResourcesLock.Unlock() entry := m.thirdPartyResources[path] @@ -599,7 +613,7 @@ func (m *Master) removeThirdPartyStorage(path, resource string) error { delete(entry.storage, resource) if len(entry.storage) == 0 { delete(m.thirdPartyResources, path) - m.RemoveAPIGroupForDiscovery(getThirdPartyGroupName(path)) + m.RemoveAPIGroupForDiscovery(extensionsrest.GetThirdPartyGroupName(path)) } else { m.thirdPartyResources[path] = entry } @@ -720,7 +734,7 @@ func (m *Master) InstallThirdPartyResource(rsrc *extensions.ThirdPartyResource) Version: rsrc.Versions[0].Name, Kind: kind, }) - path := makeThirdPartyPath(group) + path := extensionsrest.MakeThirdPartyPath(group) groupVersion := unversioned.GroupVersionForDiscovery{ GroupVersion: group + "/" + rsrc.Versions[0].Name, @@ -770,7 +784,7 @@ func (m *Master) thirdpartyapi(group, kind, version, pluralResource string) *api internalVersion := unversioned.GroupVersion{Group: group, Version: runtime.APIVersionInternal} externalVersion := unversioned.GroupVersion{Group: group, Version: version} - apiRoot := makeThirdPartyPath("") + apiRoot := extensionsrest.MakeThirdPartyPath("") return &apiserver.APIGroupVersion{ Root: apiRoot, GroupVersion: externalVersion, @@ -793,7 +807,7 @@ func (m *Master) thirdpartyapi(group, kind, version, pluralResource string) *api MinRequestTimeout: m.MinRequestTimeout(), - ResourceLister: dynamicLister{m, makeThirdPartyPath(group)}, + ResourceLister: dynamicLister{m, extensionsrest.MakeThirdPartyPath(group)}, } } diff --git a/pkg/master/master_test.go b/pkg/master/master_test.go index 17d6470a98b..931ef81c02e 100644 --- a/pkg/master/master_test.go +++ b/pkg/master/master_test.go @@ -53,6 +53,7 @@ import ( "k8s.io/kubernetes/pkg/registry/core/endpoint" "k8s.io/kubernetes/pkg/registry/core/namespace" ipallocator "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" + extensionsrest "k8s.io/kubernetes/pkg/registry/extensions/rest" "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata" "k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/registrytest" @@ -1127,7 +1128,7 @@ func testInstallThirdPartyResourceRemove(t *testing.T, version string) { t.Errorf("expected:\n%v\nsaw:\n%v\n", expectedObj, item) } - path := makeThirdPartyPath("company.com") + path := extensionsrest.MakeThirdPartyPath("company.com") master.RemoveThirdPartyResource(path + "/foos") resp, err = http.Get(server.URL + "/apis/company.com/" + version + "/namespaces/default/foos/test") diff --git a/pkg/master/thirdparty_controller.go b/pkg/master/thirdparty_controller.go index b6069b83e01..1ebd83293fd 100644 --- a/pkg/master/thirdparty_controller.go +++ b/pkg/master/thirdparty_controller.go @@ -17,21 +17,10 @@ limitations under the License. package master import ( - "fmt" - "strings" - - "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/unversioned" - expapi "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apiserver" - thirdpartyresourceetcd "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresource/etcd" - "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/sets" ) -const thirdpartyprefix = "/apis" - // dynamicLister is used to list resources for dynamic third party // apis. It implements the apiserver.APIResourceLister interface type dynamicLister struct { @@ -44,103 +33,3 @@ func (d dynamicLister) ListAPIResources() []unversioned.APIResource { } var _ apiserver.APIResourceLister = &dynamicLister{} - -func makeThirdPartyPath(group string) string { - if len(group) == 0 { - return thirdpartyprefix - } - return thirdpartyprefix + "/" + group -} - -func getThirdPartyGroupName(path string) string { - return strings.TrimPrefix(strings.TrimPrefix(path, thirdpartyprefix), "/") -} - -// resourceInterface is the interface for the parts of the master that know how to add/remove -// third party resources. Extracted into an interface for injection for testing. -type resourceInterface interface { - // Remove a third party resource based on the RESTful path for that resource, the path is / - RemoveThirdPartyResource(path string) error - // Install a third party resource described by 'rsrc' - InstallThirdPartyResource(rsrc *expapi.ThirdPartyResource) error - // Is a particular third party resource currently installed? - HasThirdPartyResource(rsrc *expapi.ThirdPartyResource) (bool, error) - // List all currently installed third party resources, the returned - // names are of the form / - ListThirdPartyResources() []string -} - -// ThirdPartyController is a control loop that knows how to synchronize ThirdPartyResource objects with -// RESTful resources which are present in the API server. -type ThirdPartyController struct { - master resourceInterface - thirdPartyResourceRegistry *thirdpartyresourceetcd.REST -} - -// Synchronize a single resource with RESTful resources on the master -func (t *ThirdPartyController) SyncOneResource(rsrc *expapi.ThirdPartyResource) error { - // TODO: we also need to test if the existing installed resource matches the resource we are sync-ing. - // Currently, if there is an older, incompatible resource installed, we won't remove it. We should detect - // older, incompatible resources and remove them before testing if the resource exists. - hasResource, err := t.master.HasThirdPartyResource(rsrc) - if err != nil { - return err - } - if !hasResource { - return t.master.InstallThirdPartyResource(rsrc) - } - return nil -} - -// Synchronize all resources with RESTful resources on the master -func (t *ThirdPartyController) SyncResources() error { - list, err := t.thirdPartyResourceRegistry.List(api.NewDefaultContext(), nil) - if err != nil { - return err - } - return t.syncResourceList(list) -} - -func (t *ThirdPartyController) syncResourceList(list runtime.Object) error { - existing := sets.String{} - switch list := list.(type) { - case *expapi.ThirdPartyResourceList: - // Loop across all schema objects for third party resources - for ix := range list.Items { - item := &list.Items[ix] - // extract the api group and resource kind from the schema - _, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(item) - if err != nil { - return err - } - // place it in the set of resources that we expect, so that we don't delete it in the delete pass - existing.Insert(makeThirdPartyPath(group)) - // ensure a RESTful resource for this schema exists on the master - if err := t.SyncOneResource(item); err != nil { - return err - } - } - default: - return fmt.Errorf("expected a *ThirdPartyResourceList, got %#v", list) - } - // deletion phase, get all installed RESTful resources - installed := t.master.ListThirdPartyResources() - for _, installedAPI := range installed { - found := false - // search across the expected restful resources to see if this resource belongs to one of the expected ones - for _, apiPath := range existing.List() { - if installedAPI == apiPath || strings.HasPrefix(installedAPI, apiPath+"/") { - found = true - break - } - } - // not expected, delete the resource - if !found { - if err := t.master.RemoveThirdPartyResource(installedAPI); err != nil { - return err - } - } - } - - return nil -} diff --git a/pkg/master/storage_apps.go b/pkg/registry/apps/rest/storage_apps.go similarity index 75% rename from pkg/master/storage_apps.go rename to pkg/registry/apps/rest/storage_apps.go index 04281a0190b..2b71436d9bb 100644 --- a/pkg/master/storage_apps.go +++ b/pkg/registry/apps/rest/storage_apps.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package master +package rest import ( "k8s.io/kubernetes/pkg/api/rest" @@ -24,11 +24,11 @@ import ( petsetetcd "k8s.io/kubernetes/pkg/registry/apps/petset/etcd" ) -type AppsRESTStorageProvider struct{} +type RESTStorageProvider struct{} -var _ genericapiserver.RESTStorageProvider = &AppsRESTStorageProvider{} +var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{} -func (p AppsRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apps.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(appsapiv1alpha1.SchemeGroupVersion) { @@ -39,7 +39,7 @@ func (p AppsRESTStorageProvider) NewRESTStorage(apiResourceConfigSource generica return apiGroupInfo, true } -func (p AppsRESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { version := appsapiv1alpha1.SchemeGroupVersion storage := map[string]rest.Storage{} diff --git a/pkg/master/storage_authentication.go b/pkg/registry/authentication/rest/storage_authentication.go similarity index 77% rename from pkg/master/storage_authentication.go rename to pkg/registry/authentication/rest/storage_authentication.go index f2f10cad7b9..ef4dd5e4ee2 100644 --- a/pkg/master/storage_authentication.go +++ b/pkg/registry/authentication/rest/storage_authentication.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package master +package rest import ( "k8s.io/kubernetes/pkg/api/rest" @@ -25,13 +25,13 @@ import ( "k8s.io/kubernetes/pkg/registry/authentication/tokenreview" ) -type AuthenticationRESTStorageProvider struct { +type RESTStorageProvider struct { Authenticator authenticator.Request } -var _ genericapiserver.RESTStorageProvider = &AuthenticationRESTStorageProvider{} +var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{} -func (p AuthenticationRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { // TODO figure out how to make the swagger generation stable, while allowing this endpoint to be disabled. // if p.Authenticator == nil { // return genericapiserver.APIGroupInfo{}, false @@ -47,7 +47,7 @@ func (p AuthenticationRESTStorageProvider) NewRESTStorage(apiResourceConfigSourc return apiGroupInfo, true } -func (p AuthenticationRESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { version := authenticationv1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} diff --git a/pkg/master/storage_authorization.go b/pkg/registry/authorization/rest/storage_authorization.go similarity index 80% rename from pkg/master/storage_authorization.go rename to pkg/registry/authorization/rest/storage_authorization.go index 1b1d7994a54..f8af8804c5f 100644 --- a/pkg/master/storage_authorization.go +++ b/pkg/registry/authorization/rest/storage_authorization.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package master +package rest import ( "k8s.io/kubernetes/pkg/api/rest" @@ -27,13 +27,13 @@ import ( "k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview" ) -type AuthorizationRESTStorageProvider struct { +type RESTStorageProvider struct { Authorizer authorizer.Authorizer } -var _ genericapiserver.RESTStorageProvider = &AuthorizationRESTStorageProvider{} +var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{} -func (p AuthorizationRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { if p.Authorizer == nil { return genericapiserver.APIGroupInfo{}, false } @@ -48,7 +48,7 @@ func (p AuthorizationRESTStorageProvider) NewRESTStorage(apiResourceConfigSource return apiGroupInfo, true } -func (p AuthorizationRESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { version := authorizationv1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} diff --git a/pkg/master/storage_autoscaling.go b/pkg/registry/autoscaling/rest/storage_autoscaling.go similarity index 76% rename from pkg/master/storage_autoscaling.go rename to pkg/registry/autoscaling/rest/storage_autoscaling.go index 4a1f39a4bfd..dffddf08d85 100644 --- a/pkg/master/storage_autoscaling.go +++ b/pkg/registry/autoscaling/rest/storage_autoscaling.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package master +package rest import ( "k8s.io/kubernetes/pkg/api/rest" @@ -24,11 +24,11 @@ import ( horizontalpodautoscaleretcd "k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/etcd" ) -type AutoscalingRESTStorageProvider struct{} +type RESTStorageProvider struct{} -var _ genericapiserver.RESTStorageProvider = &AutoscalingRESTStorageProvider{} +var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{} -func (p AutoscalingRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(autoscaling.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(autoscalingapiv1.SchemeGroupVersion) { @@ -39,7 +39,7 @@ func (p AutoscalingRESTStorageProvider) NewRESTStorage(apiResourceConfigSource g return apiGroupInfo, true } -func (p AutoscalingRESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { version := autoscalingapiv1.SchemeGroupVersion storage := map[string]rest.Storage{} diff --git a/pkg/master/storage_batch.go b/pkg/registry/batch/rest/storage_batch.go similarity index 80% rename from pkg/master/storage_batch.go rename to pkg/registry/batch/rest/storage_batch.go index 1f15dc09e24..0cdd25722f9 100644 --- a/pkg/master/storage_batch.go +++ b/pkg/registry/batch/rest/storage_batch.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package master +package rest import ( "k8s.io/kubernetes/pkg/api/rest" @@ -26,11 +26,11 @@ import ( scheduledjobetcd "k8s.io/kubernetes/pkg/registry/batch/scheduledjob/etcd" ) -type BatchRESTStorageProvider struct{} +type RESTStorageProvider struct{} -var _ genericapiserver.RESTStorageProvider = &BatchRESTStorageProvider{} +var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{} -func (p BatchRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(batch.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv2alpha1.SchemeGroupVersion) { @@ -45,7 +45,7 @@ func (p BatchRESTStorageProvider) NewRESTStorage(apiResourceConfigSource generic return apiGroupInfo, true } -func (p BatchRESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { version := batchapiv1.SchemeGroupVersion storage := map[string]rest.Storage{} @@ -57,7 +57,7 @@ func (p BatchRESTStorageProvider) v1Storage(apiResourceConfigSource genericapise return storage } -func (p BatchRESTStorageProvider) v2alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v2alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { version := batchapiv2alpha1.SchemeGroupVersion storage := map[string]rest.Storage{} diff --git a/pkg/master/storage_certificates.go b/pkg/registry/certificates/rest/storage_certificates.go similarity index 77% rename from pkg/master/storage_certificates.go rename to pkg/registry/certificates/rest/storage_certificates.go index eb29777d442..1fcd264a9c4 100644 --- a/pkg/master/storage_certificates.go +++ b/pkg/registry/certificates/rest/storage_certificates.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package master +package rest import ( "k8s.io/kubernetes/pkg/api/rest" @@ -24,11 +24,11 @@ import ( certificateetcd "k8s.io/kubernetes/pkg/registry/certificates/certificates/etcd" ) -type CertificatesRESTStorageProvider struct{} +type RESTStorageProvider struct{} -var _ genericapiserver.RESTStorageProvider = &CertificatesRESTStorageProvider{} +var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{} -func (p CertificatesRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(certificates.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(certificatesapiv1alpha1.SchemeGroupVersion) { @@ -39,7 +39,7 @@ func (p CertificatesRESTStorageProvider) NewRESTStorage(apiResourceConfigSource return apiGroupInfo, true } -func (p CertificatesRESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { version := certificatesapiv1alpha1.SchemeGroupVersion storage := map[string]rest.Storage{} diff --git a/pkg/master/storage_extensions.go b/pkg/registry/extensions/rest/storage_extensions.go similarity index 90% rename from pkg/master/storage_extensions.go rename to pkg/registry/extensions/rest/storage_extensions.go index bf1c4fbd7da..68568b154ee 100644 --- a/pkg/master/storage_extensions.go +++ b/pkg/registry/extensions/rest/storage_extensions.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package master +package rest import ( "time" @@ -39,14 +39,14 @@ import ( "k8s.io/kubernetes/pkg/util/wait" ) -type ExtensionsRESTStorageProvider struct { - ResourceInterface resourceInterface +type RESTStorageProvider struct { + ResourceInterface ResourceInterface DisableThirdPartyControllerForTesting bool } -var _ genericapiserver.RESTStorageProvider = &ExtensionsRESTStorageProvider{} +var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{} -func (p ExtensionsRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(extensions.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) { @@ -57,7 +57,7 @@ func (p ExtensionsRESTStorageProvider) NewRESTStorage(apiResourceConfigSource ge return apiGroupInfo, true } -func (p ExtensionsRESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { version := extensionsapiv1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} diff --git a/pkg/registry/extensions/rest/thirdparty_controller.go b/pkg/registry/extensions/rest/thirdparty_controller.go new file mode 100644 index 00000000000..f4aed6c36db --- /dev/null +++ b/pkg/registry/extensions/rest/thirdparty_controller.go @@ -0,0 +1,131 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rest + +import ( + "fmt" + "strings" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" + thirdpartyresourceetcd "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresource/etcd" + "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata" + "k8s.io/kubernetes/pkg/runtime" + "k8s.io/kubernetes/pkg/util/sets" +) + +// ResourceInterface is the interface for the parts of the master that know how to add/remove +// third party resources. Extracted into an interface for injection for testing. +type ResourceInterface interface { + // Remove a third party resource based on the RESTful path for that resource, the path is / + RemoveThirdPartyResource(path string) error + // Install a third party resource described by 'rsrc' + InstallThirdPartyResource(rsrc *extensions.ThirdPartyResource) error + // Is a particular third party resource currently installed? + HasThirdPartyResource(rsrc *extensions.ThirdPartyResource) (bool, error) + // List all currently installed third party resources, the returned + // names are of the form / + ListThirdPartyResources() []string +} + +const thirdpartyprefix = "/apis" + +// ThirdPartyController is a control loop that knows how to synchronize ThirdPartyResource objects with +// RESTful resources which are present in the API server. +type ThirdPartyController struct { + master ResourceInterface + thirdPartyResourceRegistry *thirdpartyresourceetcd.REST +} + +// Synchronize a single resource with RESTful resources on the master +func (t *ThirdPartyController) SyncOneResource(rsrc *extensions.ThirdPartyResource) error { + // TODO: we also need to test if the existing installed resource matches the resource we are sync-ing. + // Currently, if there is an older, incompatible resource installed, we won't remove it. We should detect + // older, incompatible resources and remove them before testing if the resource exists. + hasResource, err := t.master.HasThirdPartyResource(rsrc) + if err != nil { + return err + } + if !hasResource { + return t.master.InstallThirdPartyResource(rsrc) + } + return nil +} + +// Synchronize all resources with RESTful resources on the master +func (t *ThirdPartyController) SyncResources() error { + list, err := t.thirdPartyResourceRegistry.List(api.NewDefaultContext(), nil) + if err != nil { + return err + } + return t.syncResourceList(list) +} + +func (t *ThirdPartyController) syncResourceList(list runtime.Object) error { + existing := sets.String{} + switch list := list.(type) { + case *extensions.ThirdPartyResourceList: + // Loop across all schema objects for third party resources + for ix := range list.Items { + item := &list.Items[ix] + // extract the api group and resource kind from the schema + _, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(item) + if err != nil { + return err + } + // place it in the set of resources that we expect, so that we don't delete it in the delete pass + existing.Insert(MakeThirdPartyPath(group)) + // ensure a RESTful resource for this schema exists on the master + if err := t.SyncOneResource(item); err != nil { + return err + } + } + default: + return fmt.Errorf("expected a *ThirdPartyResourceList, got %#v", list) + } + // deletion phase, get all installed RESTful resources + installed := t.master.ListThirdPartyResources() + for _, installedAPI := range installed { + found := false + // search across the expected restful resources to see if this resource belongs to one of the expected ones + for _, apiPath := range existing.List() { + if installedAPI == apiPath || strings.HasPrefix(installedAPI, apiPath+"/") { + found = true + break + } + } + // not expected, delete the resource + if !found { + if err := t.master.RemoveThirdPartyResource(installedAPI); err != nil { + return err + } + } + } + + return nil +} + +func MakeThirdPartyPath(group string) string { + if len(group) == 0 { + return thirdpartyprefix + } + return thirdpartyprefix + "/" + group +} + +func GetThirdPartyGroupName(path string) string { + return strings.TrimPrefix(strings.TrimPrefix(path, thirdpartyprefix), "/") +} diff --git a/pkg/master/thirdparty_controller_test.go b/pkg/registry/extensions/rest/thirdparty_controller_test.go similarity index 97% rename from pkg/master/thirdparty_controller_test.go rename to pkg/registry/extensions/rest/thirdparty_controller_test.go index b9fa661a3e8..92241762235 100644 --- a/pkg/master/thirdparty_controller_test.go +++ b/pkg/registry/extensions/rest/thirdparty_controller_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package master +package rest import ( "testing" @@ -40,7 +40,7 @@ func (f *FakeAPIInterface) RemoveThirdPartyResource(path string) error { func (f *FakeAPIInterface) InstallThirdPartyResource(rsrc *expapi.ThirdPartyResource) error { f.installed = append(f.installed, rsrc) _, group, _ := thirdpartyresourcedata.ExtractApiGroupAndKind(rsrc) - f.apis = append(f.apis, makeThirdPartyPath(group)) + f.apis = append(f.apis, MakeThirdPartyPath(group)) return nil } @@ -49,7 +49,7 @@ func (f *FakeAPIInterface) HasThirdPartyResource(rsrc *expapi.ThirdPartyResource return false, nil } _, group, _ := thirdpartyresourcedata.ExtractApiGroupAndKind(rsrc) - path := makeThirdPartyPath(group) + path := MakeThirdPartyPath(group) for _, api := range f.apis { if api == path { return true, nil diff --git a/pkg/master/storage_policy.go b/pkg/registry/policy/rest/storage_policy.go similarity index 76% rename from pkg/master/storage_policy.go rename to pkg/registry/policy/rest/storage_policy.go index c593806790a..b5a5cc66bb8 100644 --- a/pkg/master/storage_policy.go +++ b/pkg/registry/policy/rest/storage_policy.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package master +package rest import ( "k8s.io/kubernetes/pkg/api/rest" @@ -24,11 +24,11 @@ import ( poddisruptionbudgetetcd "k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/etcd" ) -type PolicyRESTStorageProvider struct{} +type RESTStorageProvider struct{} -var _ genericapiserver.RESTStorageProvider = &PolicyRESTStorageProvider{} +var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{} -func (p PolicyRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(policy.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(policyapiv1alpha1.SchemeGroupVersion) { @@ -39,7 +39,7 @@ func (p PolicyRESTStorageProvider) NewRESTStorage(apiResourceConfigSource generi return apiGroupInfo, true } -func (p PolicyRESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { version := policyapiv1alpha1.SchemeGroupVersion storage := map[string]rest.Storage{} diff --git a/pkg/registry/rbac/storage/storage_rbac.go b/pkg/registry/rbac/rest/storage_rbac.go similarity index 99% rename from pkg/registry/rbac/storage/storage_rbac.go rename to pkg/registry/rbac/rest/storage_rbac.go index 2cfb7e82aaf..0259d283be7 100644 --- a/pkg/registry/rbac/storage/storage_rbac.go +++ b/pkg/registry/rbac/rest/storage_rbac.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package storage +package rest import ( "fmt" diff --git a/pkg/master/storage_storage.go b/pkg/registry/storage/rest/storage_storage.go similarity index 75% rename from pkg/master/storage_storage.go rename to pkg/registry/storage/rest/storage_storage.go index f3814b74a1f..96c1477482c 100644 --- a/pkg/master/storage_storage.go +++ b/pkg/registry/storage/rest/storage_storage.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package master +package rest import ( "k8s.io/kubernetes/pkg/api/rest" @@ -24,12 +24,12 @@ import ( storageclassetcd "k8s.io/kubernetes/pkg/registry/storage/storageclass/etcd" ) -type StorageRESTStorageProvider struct { +type RESTStorageProvider struct { } -var _ genericapiserver.RESTStorageProvider = &StorageRESTStorageProvider{} +var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{} -func (p StorageRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(storageapi.GroupName) if apiResourceConfigSource.AnyResourcesForVersionEnabled(storageapiv1beta1.SchemeGroupVersion) { @@ -40,7 +40,7 @@ func (p StorageRESTStorageProvider) NewRESTStorage(apiResourceConfigSource gener return apiGroupInfo, true } -func (p StorageRESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage { version := storageapiv1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} From 789769148301c5c0ad24cda57febd441c1c34422 Mon Sep 17 00:00:00 2001 From: deads2k Date: Fri, 23 Sep 2016 16:24:24 -0400 Subject: [PATCH 2/2] move straggler registry package --- pkg/master/master.go | 2 +- pkg/registry/{ => core}/controller/doc.go | 2 +- pkg/registry/{ => core}/controller/etcd/etcd.go | 2 +- pkg/registry/{ => core}/controller/etcd/etcd_test.go | 0 pkg/registry/{ => core}/controller/registry.go | 0 pkg/registry/{ => core}/controller/strategy.go | 0 pkg/registry/{ => core}/controller/strategy_test.go | 0 pkg/registry/extensions/controller/etcd/etcd.go | 4 ++-- 8 files changed, 5 insertions(+), 5 deletions(-) rename pkg/registry/{ => core}/controller/doc.go (90%) rename pkg/registry/{ => core}/controller/etcd/etcd.go (99%) rename pkg/registry/{ => core}/controller/etcd/etcd_test.go (100%) rename pkg/registry/{ => core}/controller/registry.go (100%) rename pkg/registry/{ => core}/controller/strategy.go (100%) rename pkg/registry/{ => core}/controller/strategy_test.go (100%) diff --git a/pkg/master/master.go b/pkg/master/master.go index 6a3cd75c69d..7ff46b6affe 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -80,9 +80,9 @@ import ( storagerest "k8s.io/kubernetes/pkg/registry/storage/rest" // direct etcd registry dependencies - controlleretcd "k8s.io/kubernetes/pkg/registry/controller/etcd" "k8s.io/kubernetes/pkg/registry/core/componentstatus" configmapetcd "k8s.io/kubernetes/pkg/registry/core/configmap/etcd" + controlleretcd "k8s.io/kubernetes/pkg/registry/core/controller/etcd" "k8s.io/kubernetes/pkg/registry/core/endpoint" endpointsetcd "k8s.io/kubernetes/pkg/registry/core/endpoint/etcd" eventetcd "k8s.io/kubernetes/pkg/registry/core/event/etcd" diff --git a/pkg/registry/controller/doc.go b/pkg/registry/core/controller/doc.go similarity index 90% rename from pkg/registry/controller/doc.go rename to pkg/registry/core/controller/doc.go index 456e7635cd4..f7e7bec2624 100644 --- a/pkg/registry/controller/doc.go +++ b/pkg/registry/core/controller/doc.go @@ -16,4 +16,4 @@ limitations under the License. // Package controller provides Registry interface and it's RESTStorage // implementation for storing ReplicationController api objects. -package controller // import "k8s.io/kubernetes/pkg/registry/controller" +package controller // import "k8s.io/kubernetes/pkg/registry/core/controller" diff --git a/pkg/registry/controller/etcd/etcd.go b/pkg/registry/core/controller/etcd/etcd.go similarity index 99% rename from pkg/registry/controller/etcd/etcd.go rename to pkg/registry/core/controller/etcd/etcd.go index 04ef3bb0254..2c037d351b1 100644 --- a/pkg/registry/controller/etcd/etcd.go +++ b/pkg/registry/core/controller/etcd/etcd.go @@ -28,7 +28,7 @@ import ( "k8s.io/kubernetes/pkg/apis/autoscaling/validation" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/registry/cachesize" - "k8s.io/kubernetes/pkg/registry/controller" + "k8s.io/kubernetes/pkg/registry/core/controller" "k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic/registry" "k8s.io/kubernetes/pkg/runtime" diff --git a/pkg/registry/controller/etcd/etcd_test.go b/pkg/registry/core/controller/etcd/etcd_test.go similarity index 100% rename from pkg/registry/controller/etcd/etcd_test.go rename to pkg/registry/core/controller/etcd/etcd_test.go diff --git a/pkg/registry/controller/registry.go b/pkg/registry/core/controller/registry.go similarity index 100% rename from pkg/registry/controller/registry.go rename to pkg/registry/core/controller/registry.go diff --git a/pkg/registry/controller/strategy.go b/pkg/registry/core/controller/strategy.go similarity index 100% rename from pkg/registry/controller/strategy.go rename to pkg/registry/core/controller/strategy.go diff --git a/pkg/registry/controller/strategy_test.go b/pkg/registry/core/controller/strategy_test.go similarity index 100% rename from pkg/registry/controller/strategy_test.go rename to pkg/registry/core/controller/strategy_test.go diff --git a/pkg/registry/extensions/controller/etcd/etcd.go b/pkg/registry/extensions/controller/etcd/etcd.go index ee8a15bcf7a..0b9510e365a 100644 --- a/pkg/registry/extensions/controller/etcd/etcd.go +++ b/pkg/registry/extensions/controller/etcd/etcd.go @@ -23,8 +23,8 @@ import ( "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/registry/controller" - "k8s.io/kubernetes/pkg/registry/controller/etcd" + "k8s.io/kubernetes/pkg/registry/core/controller" + "k8s.io/kubernetes/pkg/registry/core/controller/etcd" "k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/runtime"