From c30690a3bb6eb5783cfb7e452552992e1fcee549 Mon Sep 17 00:00:00 2001 From: deads2k Date: Wed, 27 Jul 2016 10:29:31 -0400 Subject: [PATCH] separate out api group storage registration --- api/swagger-spec/resourceListing.json | 16 +- pkg/genericapiserver/genericapiserver.go | 16 ++ pkg/master/master.go | 327 ++--------------------- pkg/master/storage_apps.go | 52 ++++ pkg/master/storage_autoscaling.go | 52 ++++ pkg/master/storage_batch.go | 69 +++++ pkg/master/storage_certificates.go | 53 ++++ pkg/master/storage_extensions.go | 133 +++++++++ pkg/master/storage_policy.go | 52 ++++ pkg/master/storage_rbac.go | 93 +++++++ 10 files changed, 546 insertions(+), 317 deletions(-) create mode 100644 pkg/master/storage_apps.go create mode 100644 pkg/master/storage_autoscaling.go create mode 100644 pkg/master/storage_batch.go create mode 100644 pkg/master/storage_certificates.go create mode 100644 pkg/master/storage_extensions.go create mode 100644 pkg/master/storage_policy.go create mode 100644 pkg/master/storage_rbac.go diff --git a/api/swagger-spec/resourceListing.json b/api/swagger-spec/resourceListing.json index de827cb8406..01d04c871b5 100644 --- a/api/swagger-spec/resourceListing.json +++ b/api/swagger-spec/resourceListing.json @@ -17,14 +17,6 @@ "path": "/api", "description": "get available API versions" }, - { - "path": "/apis/extensions/v1beta1", - "description": "API at /apis/extensions/v1beta1" - }, - { - "path": "/apis/extensions", - "description": "get information of a group" - }, { "path": "/apis/apps/v1alpha1", "description": "API at /apis/apps/v1alpha1" @@ -61,6 +53,14 @@ "path": "/apis/certificates", "description": "get information of a group" }, + { + "path": "/apis/extensions/v1beta1", + "description": "API at /apis/extensions/v1beta1" + }, + { + "path": "/apis/extensions", + "description": "get information of a group" + }, { "path": "/apis/policy/v1alpha1", "description": "API at /apis/policy/v1alpha1" diff --git a/pkg/genericapiserver/genericapiserver.go b/pkg/genericapiserver/genericapiserver.go index 9b0cc5baf23..dcc0e72739d 100644 --- a/pkg/genericapiserver/genericapiserver.go +++ b/pkg/genericapiserver/genericapiserver.go @@ -35,6 +35,7 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/apimachinery" + "k8s.io/kubernetes/pkg/apimachinery/registered" "k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/auth/authenticator" "k8s.io/kubernetes/pkg/auth/authorizer" @@ -918,3 +919,18 @@ func (s *GenericAPIServer) InstallSwaggerAPI() { } swagger.RegisterSwaggerService(swaggerConfig, s.HandlerContainer) } + +// NewDefaultAPIGroupInfo returns an APIGroupInfo stubbed with "normal" values +// exposed for easier composition from other packages +func NewDefaultAPIGroupInfo(group string) APIGroupInfo { + groupMeta := registered.GroupOrDie(group) + + return APIGroupInfo{ + GroupMeta: *groupMeta, + VersionedResourcesStorageMap: map[string]map[string]rest.Storage{}, + OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion, + Scheme: api.Scheme, + ParameterCodec: api.ParameterCodec, + NegotiatedSerializer: api.Codecs, + } +} diff --git a/pkg/master/master.go b/pkg/master/master.go index 13de194f164..20d97ff2d0f 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -33,13 +33,11 @@ import ( "k8s.io/kubernetes/pkg/api/unversioned" apiv1 "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/apis/apps" appsapi "k8s.io/kubernetes/pkg/apis/apps/v1alpha1" "k8s.io/kubernetes/pkg/apis/autoscaling" autoscalingapiv1 "k8s.io/kubernetes/pkg/apis/autoscaling/v1" "k8s.io/kubernetes/pkg/apis/batch" batchapiv1 "k8s.io/kubernetes/pkg/apis/batch/v1" - batchapiv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1" "k8s.io/kubernetes/pkg/apis/certificates" certificatesapiv1alpha1 "k8s.io/kubernetes/pkg/apis/certificates/v1alpha1" "k8s.io/kubernetes/pkg/apis/extensions" @@ -48,60 +46,35 @@ import ( policyapiv1alpha1 "k8s.io/kubernetes/pkg/apis/policy/v1alpha1" "k8s.io/kubernetes/pkg/apis/rbac" rbacapi "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1" - rbacvalidation "k8s.io/kubernetes/pkg/apis/rbac/validation" "k8s.io/kubernetes/pkg/apiserver" apiservermetrics "k8s.io/kubernetes/pkg/apiserver/metrics" "k8s.io/kubernetes/pkg/genericapiserver" "k8s.io/kubernetes/pkg/healthz" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/master/ports" - certificateetcd "k8s.io/kubernetes/pkg/registry/certificates/etcd" - "k8s.io/kubernetes/pkg/registry/clusterrole" - clusterroleetcd "k8s.io/kubernetes/pkg/registry/clusterrole/etcd" - clusterrolepolicybased "k8s.io/kubernetes/pkg/registry/clusterrole/policybased" - "k8s.io/kubernetes/pkg/registry/clusterrolebinding" - clusterrolebindingetcd "k8s.io/kubernetes/pkg/registry/clusterrolebinding/etcd" - clusterrolebindingpolicybased "k8s.io/kubernetes/pkg/registry/clusterrolebinding/policybased" "k8s.io/kubernetes/pkg/registry/componentstatus" configmapetcd "k8s.io/kubernetes/pkg/registry/configmap/etcd" controlleretcd "k8s.io/kubernetes/pkg/registry/controller/etcd" - deploymentetcd "k8s.io/kubernetes/pkg/registry/deployment/etcd" "k8s.io/kubernetes/pkg/registry/endpoint" endpointsetcd "k8s.io/kubernetes/pkg/registry/endpoint/etcd" eventetcd "k8s.io/kubernetes/pkg/registry/event/etcd" - expcontrolleretcd "k8s.io/kubernetes/pkg/registry/experimental/controller/etcd" "k8s.io/kubernetes/pkg/registry/generic" - ingressetcd "k8s.io/kubernetes/pkg/registry/ingress/etcd" - jobetcd "k8s.io/kubernetes/pkg/registry/job/etcd" limitrangeetcd "k8s.io/kubernetes/pkg/registry/limitrange/etcd" "k8s.io/kubernetes/pkg/registry/namespace" namespaceetcd "k8s.io/kubernetes/pkg/registry/namespace/etcd" - networkpolicyetcd "k8s.io/kubernetes/pkg/registry/networkpolicy/etcd" "k8s.io/kubernetes/pkg/registry/node" nodeetcd "k8s.io/kubernetes/pkg/registry/node/etcd" pvetcd "k8s.io/kubernetes/pkg/registry/persistentvolume/etcd" pvcetcd "k8s.io/kubernetes/pkg/registry/persistentvolumeclaim/etcd" - petsetetcd "k8s.io/kubernetes/pkg/registry/petset/etcd" podetcd "k8s.io/kubernetes/pkg/registry/pod/etcd" - poddisruptionbudgetetcd "k8s.io/kubernetes/pkg/registry/poddisruptionbudget/etcd" - pspetcd "k8s.io/kubernetes/pkg/registry/podsecuritypolicy/etcd" podtemplateetcd "k8s.io/kubernetes/pkg/registry/podtemplate/etcd" - replicasetetcd "k8s.io/kubernetes/pkg/registry/replicaset/etcd" resourcequotaetcd "k8s.io/kubernetes/pkg/registry/resourcequota/etcd" - "k8s.io/kubernetes/pkg/registry/role" - roleetcd "k8s.io/kubernetes/pkg/registry/role/etcd" - rolepolicybased "k8s.io/kubernetes/pkg/registry/role/policybased" - "k8s.io/kubernetes/pkg/registry/rolebinding" - rolebindingetcd "k8s.io/kubernetes/pkg/registry/rolebinding/etcd" - rolebindingpolicybased "k8s.io/kubernetes/pkg/registry/rolebinding/policybased" secretetcd "k8s.io/kubernetes/pkg/registry/secret/etcd" "k8s.io/kubernetes/pkg/registry/service" etcdallocator "k8s.io/kubernetes/pkg/registry/service/allocator/etcd" serviceetcd "k8s.io/kubernetes/pkg/registry/service/etcd" ipallocator "k8s.io/kubernetes/pkg/registry/service/ipallocator" serviceaccountetcd "k8s.io/kubernetes/pkg/registry/serviceaccount/etcd" - storageclassetcd "k8s.io/kubernetes/pkg/registry/storageclass/etcd" - thirdpartyresourceetcd "k8s.io/kubernetes/pkg/registry/thirdpartyresource/etcd" "k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata" thirdpartyresourcedataetcd "k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/etcd" "k8s.io/kubernetes/pkg/runtime" @@ -109,10 +82,6 @@ import ( etcdmetrics "k8s.io/kubernetes/pkg/storage/etcd/metrics" etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util" "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/util/wait" - - daemonetcd "k8s.io/kubernetes/pkg/registry/daemonset/etcd" - horizontalpodautoscaleretcd "k8s.io/kubernetes/pkg/registry/horizontalpodautoscaler/etcd" "github.com/golang/glog" "github.com/prometheus/client_golang/prometheus" @@ -189,7 +158,10 @@ type thirdPartyEntry struct { } type RESTOptionsGetter func(resource unversioned.GroupResource) generic.RESTOptions -type RESTStorageProvider func(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) + +type RESTStorageProvider interface { + NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) +} // New returns a new instance of Master from the given config. // Certain config fields will be set to a default value if unset. @@ -218,12 +190,16 @@ func New(c *Config) (*Master, error) { if c.RESTStorageProviders == nil { c.RESTStorageProviders = map[string]RESTStorageProvider{} } - c.RESTStorageProviders[autoscaling.GroupName] = buildAutoscalingResources - c.RESTStorageProviders[batch.GroupName] = buildBatchResources - c.RESTStorageProviders[policy.GroupName] = buildPolicyResources - c.RESTStorageProviders[appsapi.GroupName] = buildAppsResources - c.RESTStorageProviders[rbac.GroupName] = buildRBACResources(c.AuthorizerRBACSuperUser) - c.RESTStorageProviders[certificates.GroupName] = buildCertificateResources + 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{ + ResourceInterface: m, + DisableThirdPartyControllerForTesting: m.disableThirdPartyControllerForTesting, + } + c.RESTStorageProviders[policy.GroupName] = PolicyRESTStorageProvider{} + c.RESTStorageProviders[rbac.GroupName] = RBACRESTStorageProvider{AuthorizerRBACSuperUser: c.AuthorizerRBACSuperUser} m.InstallAPIs(c) // TODO: Attempt clean shutdown? @@ -290,29 +266,15 @@ func (m *Master) InstallAPIs(c *Config) { m.MuxHelper.HandleFunc("/metrics", defaultMetricsHandler) } - // Install extensions unless disabled. - if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) { + // Install third party resource support if requested + // TODO seems like this bit ought to be unconditional and the REST API is controlled by the config + if c.APIResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("thirdpartyresources")) { var err error m.thirdPartyStorage, err = c.StorageFactory.New(extensions.Resource("thirdpartyresources")) if err != nil { glog.Fatalf("Error getting third party storage: %v", err) } m.thirdPartyResources = map[string]thirdPartyEntry{} - - extensionResources := m.getExtensionResources(c) - extensionsGroupMeta := registered.GroupOrDie(extensions.GroupName) - - apiGroupInfo := genericapiserver.APIGroupInfo{ - GroupMeta: *extensionsGroupMeta, - VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ - "v1beta1": extensionResources, - }, - OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion, - Scheme: api.Scheme, - ParameterCodec: api.ParameterCodec, - NegotiatedSerializer: api.Codecs, - } - apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo) } restOptionsGetter := func(resource unversioned.GroupResource) generic.RESTOptions { @@ -326,7 +288,7 @@ func (m *Master) InstallAPIs(c *Config) { continue } restStorageBuilder := c.RESTStorageProviders[group] - apiGroupInfo, enabled := restStorageBuilder(c.APIResourceConfigSource, restOptionsGetter) + apiGroupInfo, enabled := restStorageBuilder.NewRESTStorage(c.APIResourceConfigSource, restOptionsGetter) if !enabled { continue } @@ -736,259 +698,6 @@ func (m *Master) GetRESTOptionsOrDie(c *Config, resource unversioned.GroupResour } } -// getExperimentalResources returns the resources for extensions api -func (m *Master) getExtensionResources(c *Config) map[string]rest.Storage { - restOptions := func(resource string) generic.RESTOptions { - return m.GetRESTOptionsOrDie(c, extensions.Resource(resource)) - } - - // TODO update when we support more than one version of this group - version := extensionsapiv1beta1.SchemeGroupVersion - - storage := map[string]rest.Storage{} - - if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("horizontalpodautoscalers")) { - hpaStorage, hpaStatusStorage := horizontalpodautoscaleretcd.NewREST(restOptions("horizontalpodautoscalers")) - storage["horizontalpodautoscalers"] = hpaStorage - storage["horizontalpodautoscalers/status"] = hpaStatusStorage - - controllerStorage := expcontrolleretcd.NewStorage(m.GetRESTOptionsOrDie(c, api.Resource("replicationControllers"))) - storage["replicationcontrollers"] = controllerStorage.ReplicationController - storage["replicationcontrollers/scale"] = controllerStorage.Scale - } - thirdPartyResourceStorage := thirdpartyresourceetcd.NewREST(restOptions("thirdpartyresources")) - if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("thirdpartyresources")) { - thirdPartyControl := ThirdPartyController{ - master: m, - thirdPartyResourceRegistry: thirdPartyResourceStorage, - } - if !m.disableThirdPartyControllerForTesting { - go wait.Forever(func() { - if err := thirdPartyControl.SyncResources(); err != nil { - glog.Warningf("third party resource sync failed: %v", err) - } - }, 10*time.Second) - } - storage["thirdpartyresources"] = thirdPartyResourceStorage - } - - daemonSetStorage, daemonSetStatusStorage := daemonetcd.NewREST(restOptions("daemonsets")) - if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("daemonsets")) { - storage["daemonsets"] = daemonSetStorage - storage["daemonsets/status"] = daemonSetStatusStorage - } - deploymentStorage := deploymentetcd.NewStorage(restOptions("deployments")) - if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("deployments")) { - storage["deployments"] = deploymentStorage.Deployment - storage["deployments/status"] = deploymentStorage.Status - storage["deployments/rollback"] = deploymentStorage.Rollback - storage["deployments/scale"] = deploymentStorage.Scale - } - if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) { - jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptions("jobs")) - storage["jobs"] = jobsStorage - storage["jobs/status"] = jobsStatusStorage - } - ingressStorage, ingressStatusStorage := ingressetcd.NewREST(restOptions("ingresses")) - if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("ingresses")) { - storage["ingresses"] = ingressStorage - storage["ingresses/status"] = ingressStatusStorage - } - podSecurityPolicyStorage := pspetcd.NewREST(restOptions("podsecuritypolicy")) - if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("podsecuritypolicy")) { - storage["podSecurityPolicies"] = podSecurityPolicyStorage - } - replicaSetStorage := replicasetetcd.NewStorage(restOptions("replicasets")) - if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("replicasets")) { - storage["replicasets"] = replicaSetStorage.ReplicaSet - storage["replicasets/status"] = replicaSetStorage.Status - storage["replicasets/scale"] = replicaSetStorage.Scale - } - networkPolicyStorage := networkpolicyetcd.NewREST(restOptions("networkpolicies")) - if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("networkpolicies")) { - storage["networkpolicies"] = networkPolicyStorage - } - storageClassStorage := storageclassetcd.NewREST(restOptions("storageclasses")) - if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("storageclasses")) { - storage["storageclasses"] = storageClassStorage - } - - return storage -} - -// NewDefaultAPIGroupInfo returns a complete APIGroupInfo stubbed with "normal" values -// exposed for easier composition from other packages -func NewDefaultAPIGroupInfo(group string) genericapiserver.APIGroupInfo { - groupMeta := registered.GroupOrDie(group) - - return genericapiserver.APIGroupInfo{ - GroupMeta: *groupMeta, - VersionedResourcesStorageMap: map[string]map[string]rest.Storage{}, - OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion, - Scheme: api.Scheme, - ParameterCodec: api.ParameterCodec, - NegotiatedSerializer: api.Codecs, - } -} - -func buildCertificateResources(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := NewDefaultAPIGroupInfo(certificates.GroupName) - - storageForVersion := func(version unversioned.GroupVersion) map[string]rest.Storage { - storage := map[string]rest.Storage{} - if apiResourceConfigSource.ResourceEnabled(version.WithResource("certificatesigningrequests")) { - csrStorage, csrStatusStorage, csrApprovalStorage := certificateetcd.NewREST(restOptionsGetter(certificates.Resource("certificatesigningrequests"))) - storage["certificatesigningrequests"] = csrStorage - storage["certificatesigningrequests/status"] = csrStatusStorage - storage["certificatesigningrequests/approval"] = csrApprovalStorage - } - return storage - } - - if apiResourceConfigSource.AnyResourcesForVersionEnabled(certificatesapiv1alpha1.SchemeGroupVersion) { - apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1alpha1.SchemeGroupVersion.Version] = storageForVersion(certificatesapiv1alpha1.SchemeGroupVersion) - apiGroupInfo.GroupMeta.GroupVersion = certificatesapiv1alpha1.SchemeGroupVersion - } - - return apiGroupInfo, true -} - -func buildAutoscalingResources(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := NewDefaultAPIGroupInfo(autoscaling.GroupName) - - storageForVersion := func(version unversioned.GroupVersion) map[string]rest.Storage { - storage := map[string]rest.Storage{} - if apiResourceConfigSource.ResourceEnabled(version.WithResource("horizontalpodautoscalers")) { - hpaStorage, hpaStatusStorage := horizontalpodautoscaleretcd.NewREST(restOptionsGetter(autoscaling.Resource("horizontalpodautoscalers"))) - storage["horizontalpodautoscalers"] = hpaStorage - storage["horizontalpodautoscalers/status"] = hpaStatusStorage - } - return storage - } - - if apiResourceConfigSource.AnyResourcesForVersionEnabled(autoscalingapiv1.SchemeGroupVersion) { - apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv1.SchemeGroupVersion.Version] = storageForVersion(autoscalingapiv1.SchemeGroupVersion) - apiGroupInfo.GroupMeta.GroupVersion = autoscalingapiv1.SchemeGroupVersion - } - - return apiGroupInfo, true -} - -func buildBatchResources(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := NewDefaultAPIGroupInfo(batch.GroupName) - - storageForVersion := func(version unversioned.GroupVersion) map[string]rest.Storage { - storage := map[string]rest.Storage{} - if apiResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) { - jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter(batch.Resource("jobs"))) - storage["jobs"] = jobsStorage - storage["jobs/status"] = jobsStatusStorage - } - return storage - } - - if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv2alpha1.SchemeGroupVersion) { - apiGroupInfo.VersionedResourcesStorageMap[batchapiv2alpha1.SchemeGroupVersion.Version] = storageForVersion(batchapiv2alpha1.SchemeGroupVersion) - apiGroupInfo.GroupMeta.GroupVersion = batchapiv2alpha1.SchemeGroupVersion - } - if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv1.SchemeGroupVersion) { - apiGroupInfo.VersionedResourcesStorageMap[batchapiv1.SchemeGroupVersion.Version] = storageForVersion(batchapiv1.SchemeGroupVersion) - apiGroupInfo.GroupMeta.GroupVersion = batchapiv1.SchemeGroupVersion - } - - return apiGroupInfo, true -} - -func buildPolicyResources(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := NewDefaultAPIGroupInfo(policy.GroupName) - - storageForVersion := func(version unversioned.GroupVersion) map[string]rest.Storage { - storage := map[string]rest.Storage{} - if apiResourceConfigSource.ResourceEnabled(version.WithResource("poddisruptionbudgets")) { - poddisruptionbudgetStorage, poddisruptionbudgetStatusStorage := poddisruptionbudgetetcd.NewREST(restOptionsGetter(policy.Resource("poddisruptionbudgets"))) - storage["poddisruptionbudgets"] = poddisruptionbudgetStorage - storage["poddisruptionbudgets/status"] = poddisruptionbudgetStatusStorage - } - return storage - } - - if apiResourceConfigSource.AnyResourcesForVersionEnabled(policyapiv1alpha1.SchemeGroupVersion) { - apiGroupInfo.VersionedResourcesStorageMap[policyapiv1alpha1.SchemeGroupVersion.Version] = storageForVersion(policyapiv1alpha1.SchemeGroupVersion) - apiGroupInfo.GroupMeta.GroupVersion = policyapiv1alpha1.SchemeGroupVersion - } - - return apiGroupInfo, true -} - -func buildAppsResources(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := NewDefaultAPIGroupInfo(appsapi.GroupName) - - storageForVersion := func(version unversioned.GroupVersion) map[string]rest.Storage { - storage := map[string]rest.Storage{} - if apiResourceConfigSource.ResourceEnabled(version.WithResource("petsets")) { - petsetStorage, petsetStatusStorage := petsetetcd.NewREST(restOptionsGetter(apps.Resource("petsets"))) - storage["petsets"] = petsetStorage - storage["petsets/status"] = petsetStatusStorage - } - return storage - } - - if apiResourceConfigSource.AnyResourcesForVersionEnabled(appsapi.SchemeGroupVersion) { - apiGroupInfo.VersionedResourcesStorageMap[appsapi.SchemeGroupVersion.Version] = storageForVersion(appsapi.SchemeGroupVersion) - apiGroupInfo.GroupMeta.GroupVersion = appsapi.SchemeGroupVersion - } - - return apiGroupInfo, true -} - -func buildRBACResources(authorizerRBACSuperUser string) RESTStorageProvider { - return func(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := NewDefaultAPIGroupInfo(rbac.GroupName) - - storageForVersion := func(version unversioned.GroupVersion) map[string]rest.Storage { - once := new(sync.Once) - var authorizationRuleResolver rbacvalidation.AuthorizationRuleResolver - newRuleValidator := func() rbacvalidation.AuthorizationRuleResolver { - once.Do(func() { - authorizationRuleResolver = rbacvalidation.NewDefaultRuleResolver( - role.NewRegistry(roleetcd.NewREST(restOptionsGetter(rbac.Resource("roles")))), - rolebinding.NewRegistry(rolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("rolebindings")))), - clusterrole.NewRegistry(clusterroleetcd.NewREST(restOptionsGetter(rbac.Resource("clusterroles")))), - clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("clusterrolebindings")))), - ) - }) - return authorizationRuleResolver - } - - storage := map[string]rest.Storage{} - if apiResourceConfigSource.ResourceEnabled(version.WithResource("roles")) { - rolesStorage := roleetcd.NewREST(restOptionsGetter(rbac.Resource("roles"))) - storage["roles"] = rolepolicybased.NewStorage(rolesStorage, newRuleValidator(), authorizerRBACSuperUser) - } - if apiResourceConfigSource.ResourceEnabled(version.WithResource("rolebindings")) { - roleBindingsStorage := rolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("rolebindings"))) - storage["rolebindings"] = rolebindingpolicybased.NewStorage(roleBindingsStorage, newRuleValidator(), authorizerRBACSuperUser) - } - if apiResourceConfigSource.ResourceEnabled(version.WithResource("clusterroles")) { - clusterRolesStorage := clusterroleetcd.NewREST(restOptionsGetter(rbac.Resource("clusterroles"))) - storage["clusterroles"] = clusterrolepolicybased.NewStorage(clusterRolesStorage, newRuleValidator(), authorizerRBACSuperUser) - } - if apiResourceConfigSource.ResourceEnabled(version.WithResource("clusterrolebindings")) { - clusterRoleBindingsStorage := clusterrolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("clusterrolebindings"))) - storage["clusterrolebindings"] = clusterrolebindingpolicybased.NewStorage(clusterRoleBindingsStorage, newRuleValidator(), authorizerRBACSuperUser) - } - return storage - } - - if apiResourceConfigSource.AnyResourcesForVersionEnabled(rbacapi.SchemeGroupVersion) { - apiGroupInfo.VersionedResourcesStorageMap[rbacapi.SchemeGroupVersion.Version] = storageForVersion(rbacapi.SchemeGroupVersion) - apiGroupInfo.GroupMeta.GroupVersion = rbacapi.SchemeGroupVersion - } - - return apiGroupInfo, true - } -} - // findExternalAddress returns ExternalIP of provided node with fallback to LegacyHostIP. func findExternalAddress(node *api.Node) (string, error) { var fallback string diff --git a/pkg/master/storage_apps.go b/pkg/master/storage_apps.go new file mode 100644 index 00000000000..6be65f999dc --- /dev/null +++ b/pkg/master/storage_apps.go @@ -0,0 +1,52 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package master + +import ( + "k8s.io/kubernetes/pkg/api/rest" + "k8s.io/kubernetes/pkg/apis/apps" + appsapiv1alpha1 "k8s.io/kubernetes/pkg/apis/apps/v1alpha1" + "k8s.io/kubernetes/pkg/genericapiserver" + petsetetcd "k8s.io/kubernetes/pkg/registry/petset/etcd" +) + +type AppsRESTStorageProvider struct{} + +var _ RESTStorageProvider = &AppsRESTStorageProvider{} + +func (p AppsRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apps.GroupName) + + if apiResourceConfigSource.AnyResourcesForVersionEnabled(appsapiv1alpha1.SchemeGroupVersion) { + apiGroupInfo.VersionedResourcesStorageMap[appsapiv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) + apiGroupInfo.GroupMeta.GroupVersion = appsapiv1alpha1.SchemeGroupVersion + } + + return apiGroupInfo, true +} + +func (p AppsRESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage { + version := appsapiv1alpha1.SchemeGroupVersion + + storage := map[string]rest.Storage{} + if apiResourceConfigSource.ResourceEnabled(version.WithResource("petsets")) { + petsetStorage, petsetStatusStorage := petsetetcd.NewREST(restOptionsGetter(apps.Resource("petsets"))) + storage["petsets"] = petsetStorage + storage["petsets/status"] = petsetStatusStorage + } + return storage +} diff --git a/pkg/master/storage_autoscaling.go b/pkg/master/storage_autoscaling.go new file mode 100644 index 00000000000..cc628f7255e --- /dev/null +++ b/pkg/master/storage_autoscaling.go @@ -0,0 +1,52 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package master + +import ( + "k8s.io/kubernetes/pkg/api/rest" + "k8s.io/kubernetes/pkg/apis/autoscaling" + autoscalingapiv1 "k8s.io/kubernetes/pkg/apis/autoscaling/v1" + "k8s.io/kubernetes/pkg/genericapiserver" + horizontalpodautoscaleretcd "k8s.io/kubernetes/pkg/registry/horizontalpodautoscaler/etcd" +) + +type AutoscalingRESTStorageProvider struct{} + +var _ RESTStorageProvider = &AutoscalingRESTStorageProvider{} + +func (p AutoscalingRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(autoscaling.GroupName) + + if apiResourceConfigSource.AnyResourcesForVersionEnabled(autoscalingapiv1.SchemeGroupVersion) { + apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) + apiGroupInfo.GroupMeta.GroupVersion = autoscalingapiv1.SchemeGroupVersion + } + + return apiGroupInfo, true +} + +func (p AutoscalingRESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage { + version := autoscalingapiv1.SchemeGroupVersion + + storage := map[string]rest.Storage{} + if apiResourceConfigSource.ResourceEnabled(version.WithResource("horizontalpodautoscalers")) { + hpaStorage, hpaStatusStorage := horizontalpodautoscaleretcd.NewREST(restOptionsGetter(autoscaling.Resource("horizontalpodautoscalers"))) + storage["horizontalpodautoscalers"] = hpaStorage + storage["horizontalpodautoscalers/status"] = hpaStatusStorage + } + return storage +} diff --git a/pkg/master/storage_batch.go b/pkg/master/storage_batch.go new file mode 100644 index 00000000000..b6e793296e0 --- /dev/null +++ b/pkg/master/storage_batch.go @@ -0,0 +1,69 @@ +/* +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 master + +import ( + "k8s.io/kubernetes/pkg/api/rest" + "k8s.io/kubernetes/pkg/apis/batch" + batchapiv1 "k8s.io/kubernetes/pkg/apis/batch/v1" + batchapiv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1" + "k8s.io/kubernetes/pkg/genericapiserver" + jobetcd "k8s.io/kubernetes/pkg/registry/job/etcd" +) + +type BatchRESTStorageProvider struct{} + +var _ RESTStorageProvider = &BatchRESTStorageProvider{} + +func (p BatchRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(batch.GroupName) + + if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv2alpha1.SchemeGroupVersion) { + apiGroupInfo.VersionedResourcesStorageMap[batchapiv2alpha1.SchemeGroupVersion.Version] = p.v2alpha1Storage(apiResourceConfigSource, restOptionsGetter) + apiGroupInfo.GroupMeta.GroupVersion = batchapiv2alpha1.SchemeGroupVersion + } + if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv1.SchemeGroupVersion) { + apiGroupInfo.VersionedResourcesStorageMap[batchapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) + apiGroupInfo.GroupMeta.GroupVersion = batchapiv1.SchemeGroupVersion + } + + return apiGroupInfo, true +} + +func (p BatchRESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage { + version := batchapiv1.SchemeGroupVersion + + storage := map[string]rest.Storage{} + if apiResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) { + jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter(batch.Resource("jobs"))) + storage["jobs"] = jobsStorage + storage["jobs/status"] = jobsStatusStorage + } + return storage +} + +func (p BatchRESTStorageProvider) v2alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage { + version := batchapiv2alpha1.SchemeGroupVersion + + storage := map[string]rest.Storage{} + if apiResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) { + jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter(batch.Resource("jobs"))) + storage["jobs"] = jobsStorage + storage["jobs/status"] = jobsStatusStorage + } + return storage +} diff --git a/pkg/master/storage_certificates.go b/pkg/master/storage_certificates.go new file mode 100644 index 00000000000..8ee0d9ede8d --- /dev/null +++ b/pkg/master/storage_certificates.go @@ -0,0 +1,53 @@ +/* +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 master + +import ( + "k8s.io/kubernetes/pkg/api/rest" + "k8s.io/kubernetes/pkg/apis/certificates" + certificatesapiv1alpha1 "k8s.io/kubernetes/pkg/apis/certificates/v1alpha1" + "k8s.io/kubernetes/pkg/genericapiserver" + certificateetcd "k8s.io/kubernetes/pkg/registry/certificates/etcd" +) + +type CertificatesRESTStorageProvider struct{} + +var _ RESTStorageProvider = &CertificatesRESTStorageProvider{} + +func (p CertificatesRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(certificates.GroupName) + + if apiResourceConfigSource.AnyResourcesForVersionEnabled(certificatesapiv1alpha1.SchemeGroupVersion) { + apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) + apiGroupInfo.GroupMeta.GroupVersion = certificatesapiv1alpha1.SchemeGroupVersion + } + + return apiGroupInfo, true +} + +func (p CertificatesRESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage { + version := certificatesapiv1alpha1.SchemeGroupVersion + + storage := map[string]rest.Storage{} + if apiResourceConfigSource.ResourceEnabled(version.WithResource("certificatesigningrequests")) { + csrStorage, csrStatusStorage, csrApprovalStorage := certificateetcd.NewREST(restOptionsGetter(certificates.Resource("certificatesigningrequests"))) + storage["certificatesigningrequests"] = csrStorage + storage["certificatesigningrequests/status"] = csrStatusStorage + storage["certificatesigningrequests/approval"] = csrApprovalStorage + } + return storage +} diff --git a/pkg/master/storage_extensions.go b/pkg/master/storage_extensions.go new file mode 100644 index 00000000000..9e651312a65 --- /dev/null +++ b/pkg/master/storage_extensions.go @@ -0,0 +1,133 @@ +/* +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 master + +import ( + "time" + + "github.com/golang/glog" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/rest" + "k8s.io/kubernetes/pkg/apis/extensions" + extensionsapiv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" + "k8s.io/kubernetes/pkg/genericapiserver" + daemonetcd "k8s.io/kubernetes/pkg/registry/daemonset/etcd" + deploymentetcd "k8s.io/kubernetes/pkg/registry/deployment/etcd" + expcontrolleretcd "k8s.io/kubernetes/pkg/registry/experimental/controller/etcd" + horizontalpodautoscaleretcd "k8s.io/kubernetes/pkg/registry/horizontalpodautoscaler/etcd" + ingressetcd "k8s.io/kubernetes/pkg/registry/ingress/etcd" + jobetcd "k8s.io/kubernetes/pkg/registry/job/etcd" + networkpolicyetcd "k8s.io/kubernetes/pkg/registry/networkpolicy/etcd" + pspetcd "k8s.io/kubernetes/pkg/registry/podsecuritypolicy/etcd" + replicasetetcd "k8s.io/kubernetes/pkg/registry/replicaset/etcd" + storageclassetcd "k8s.io/kubernetes/pkg/registry/storageclass/etcd" + thirdpartyresourceetcd "k8s.io/kubernetes/pkg/registry/thirdpartyresource/etcd" + "k8s.io/kubernetes/pkg/util/wait" +) + +type ExtensionsRESTStorageProvider struct { + ResourceInterface resourceInterface + DisableThirdPartyControllerForTesting bool +} + +var _ RESTStorageProvider = &ExtensionsRESTStorageProvider{} + +func (p ExtensionsRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(extensions.GroupName) + + if apiResourceConfigSource.AnyResourcesForVersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) { + apiGroupInfo.VersionedResourcesStorageMap[extensionsapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) + apiGroupInfo.GroupMeta.GroupVersion = extensionsapiv1beta1.SchemeGroupVersion + } + + return apiGroupInfo, true +} + +func (p ExtensionsRESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage { + version := extensionsapiv1beta1.SchemeGroupVersion + + storage := map[string]rest.Storage{} + + if apiResourceConfigSource.ResourceEnabled(version.WithResource("horizontalpodautoscalers")) { + hpaStorage, hpaStatusStorage := horizontalpodautoscaleretcd.NewREST(restOptionsGetter(extensions.Resource("horizontalpodautoscalers"))) + storage["horizontalpodautoscalers"] = hpaStorage + storage["horizontalpodautoscalers/status"] = hpaStatusStorage + + controllerStorage := expcontrolleretcd.NewStorage(restOptionsGetter(api.Resource("replicationControllers"))) + storage["replicationcontrollers"] = controllerStorage.ReplicationController + storage["replicationcontrollers/scale"] = controllerStorage.Scale + } + if apiResourceConfigSource.ResourceEnabled(version.WithResource("thirdpartyresources")) { + thirdPartyResourceStorage := thirdpartyresourceetcd.NewREST(restOptionsGetter(extensions.Resource("thirdpartyresources"))) + thirdPartyControl := ThirdPartyController{ + master: p.ResourceInterface, + thirdPartyResourceRegistry: thirdPartyResourceStorage, + } + if !p.DisableThirdPartyControllerForTesting { + go wait.Forever(func() { + if err := thirdPartyControl.SyncResources(); err != nil { + glog.Warningf("third party resource sync failed: %v", err) + } + }, 10*time.Second) + } + storage["thirdpartyresources"] = thirdPartyResourceStorage + } + + if apiResourceConfigSource.ResourceEnabled(version.WithResource("daemonsets")) { + daemonSetStorage, daemonSetStatusStorage := daemonetcd.NewREST(restOptionsGetter(extensions.Resource("daemonsets"))) + storage["daemonsets"] = daemonSetStorage + storage["daemonsets/status"] = daemonSetStatusStorage + } + if apiResourceConfigSource.ResourceEnabled(version.WithResource("deployments")) { + deploymentStorage := deploymentetcd.NewStorage(restOptionsGetter(extensions.Resource("deployments"))) + storage["deployments"] = deploymentStorage.Deployment + storage["deployments/status"] = deploymentStorage.Status + storage["deployments/rollback"] = deploymentStorage.Rollback + storage["deployments/scale"] = deploymentStorage.Scale + } + if apiResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) { + jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter(extensions.Resource("jobs"))) + storage["jobs"] = jobsStorage + storage["jobs/status"] = jobsStatusStorage + } + if apiResourceConfigSource.ResourceEnabled(version.WithResource("ingresses")) { + ingressStorage, ingressStatusStorage := ingressetcd.NewREST(restOptionsGetter(extensions.Resource("ingresses"))) + storage["ingresses"] = ingressStorage + storage["ingresses/status"] = ingressStatusStorage + } + if apiResourceConfigSource.ResourceEnabled(version.WithResource("podsecuritypolicy")) { + podSecurityExtensionsStorage := pspetcd.NewREST(restOptionsGetter(extensions.Resource("podsecuritypolicy"))) + storage["podSecurityPolicies"] = podSecurityExtensionsStorage + } + if apiResourceConfigSource.ResourceEnabled(version.WithResource("replicasets")) { + replicaSetStorage := replicasetetcd.NewStorage(restOptionsGetter(extensions.Resource("replicasets"))) + storage["replicasets"] = replicaSetStorage.ReplicaSet + storage["replicasets/status"] = replicaSetStorage.Status + storage["replicasets/scale"] = replicaSetStorage.Scale + } + if apiResourceConfigSource.ResourceEnabled(version.WithResource("networkpolicies")) { + networkExtensionsStorage := networkpolicyetcd.NewREST(restOptionsGetter(extensions.Resource("networkpolicies"))) + storage["networkpolicies"] = networkExtensionsStorage + } + if apiResourceConfigSource.ResourceEnabled(version.WithResource("storageclasses")) { + storageClassStorage := storageclassetcd.NewREST(restOptionsGetter(extensions.Resource("storageclasses"))) + storage["storageclasses"] = storageClassStorage + } + + return storage +} diff --git a/pkg/master/storage_policy.go b/pkg/master/storage_policy.go new file mode 100644 index 00000000000..cfe11f79453 --- /dev/null +++ b/pkg/master/storage_policy.go @@ -0,0 +1,52 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package master + +import ( + "k8s.io/kubernetes/pkg/api/rest" + "k8s.io/kubernetes/pkg/apis/policy" + policyapiv1alpha1 "k8s.io/kubernetes/pkg/apis/policy/v1alpha1" + "k8s.io/kubernetes/pkg/genericapiserver" + poddisruptionbudgetetcd "k8s.io/kubernetes/pkg/registry/poddisruptionbudget/etcd" +) + +type PolicyRESTStorageProvider struct{} + +var _ RESTStorageProvider = &PolicyRESTStorageProvider{} + +func (p PolicyRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(policy.GroupName) + + if apiResourceConfigSource.AnyResourcesForVersionEnabled(policyapiv1alpha1.SchemeGroupVersion) { + apiGroupInfo.VersionedResourcesStorageMap[policyapiv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) + apiGroupInfo.GroupMeta.GroupVersion = policyapiv1alpha1.SchemeGroupVersion + } + + return apiGroupInfo, true +} + +func (p PolicyRESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage { + version := policyapiv1alpha1.SchemeGroupVersion + + storage := map[string]rest.Storage{} + if apiResourceConfigSource.ResourceEnabled(version.WithResource("poddisruptionbudgets")) { + poddisruptionbudgetStorage, poddisruptionbudgetStatusStorage := poddisruptionbudgetetcd.NewREST(restOptionsGetter(policy.Resource("poddisruptionbudgets"))) + storage["poddisruptionbudgets"] = poddisruptionbudgetStorage + storage["poddisruptionbudgets/status"] = poddisruptionbudgetStatusStorage + } + return storage +} diff --git a/pkg/master/storage_rbac.go b/pkg/master/storage_rbac.go new file mode 100644 index 00000000000..3d48026fe7d --- /dev/null +++ b/pkg/master/storage_rbac.go @@ -0,0 +1,93 @@ +/* +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 master + +import ( + "sync" + + "k8s.io/kubernetes/pkg/api/rest" + "k8s.io/kubernetes/pkg/apis/rbac" + rbacapiv1alpha1 "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1" + rbacvalidation "k8s.io/kubernetes/pkg/apis/rbac/validation" + "k8s.io/kubernetes/pkg/genericapiserver" + "k8s.io/kubernetes/pkg/registry/clusterrole" + clusterroleetcd "k8s.io/kubernetes/pkg/registry/clusterrole/etcd" + clusterrolepolicybased "k8s.io/kubernetes/pkg/registry/clusterrole/policybased" + "k8s.io/kubernetes/pkg/registry/clusterrolebinding" + clusterrolebindingetcd "k8s.io/kubernetes/pkg/registry/clusterrolebinding/etcd" + clusterrolebindingpolicybased "k8s.io/kubernetes/pkg/registry/clusterrolebinding/policybased" + "k8s.io/kubernetes/pkg/registry/role" + roleetcd "k8s.io/kubernetes/pkg/registry/role/etcd" + rolepolicybased "k8s.io/kubernetes/pkg/registry/role/policybased" + "k8s.io/kubernetes/pkg/registry/rolebinding" + rolebindingetcd "k8s.io/kubernetes/pkg/registry/rolebinding/etcd" + rolebindingpolicybased "k8s.io/kubernetes/pkg/registry/rolebinding/policybased" +) + +type RBACRESTStorageProvider struct { + AuthorizerRBACSuperUser string +} + +var _ RESTStorageProvider = &RBACRESTStorageProvider{} + +func (p RBACRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(rbac.GroupName) + + if apiResourceConfigSource.AnyResourcesForVersionEnabled(rbacapiv1alpha1.SchemeGroupVersion) { + apiGroupInfo.VersionedResourcesStorageMap[rbacapiv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) + apiGroupInfo.GroupMeta.GroupVersion = rbacapiv1alpha1.SchemeGroupVersion + } + + return apiGroupInfo, true +} + +func (p RBACRESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage { + version := rbacapiv1alpha1.SchemeGroupVersion + + once := new(sync.Once) + var authorizationRuleResolver rbacvalidation.AuthorizationRuleResolver + newRuleValidator := func() rbacvalidation.AuthorizationRuleResolver { + once.Do(func() { + authorizationRuleResolver = rbacvalidation.NewDefaultRuleResolver( + role.NewRegistry(roleetcd.NewREST(restOptionsGetter(rbac.Resource("roles")))), + rolebinding.NewRegistry(rolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("rolebindings")))), + clusterrole.NewRegistry(clusterroleetcd.NewREST(restOptionsGetter(rbac.Resource("clusterroles")))), + clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("clusterrolebindings")))), + ) + }) + return authorizationRuleResolver + } + + storage := map[string]rest.Storage{} + if apiResourceConfigSource.ResourceEnabled(version.WithResource("roles")) { + rolesStorage := roleetcd.NewREST(restOptionsGetter(rbac.Resource("roles"))) + storage["roles"] = rolepolicybased.NewStorage(rolesStorage, newRuleValidator(), p.AuthorizerRBACSuperUser) + } + if apiResourceConfigSource.ResourceEnabled(version.WithResource("rolebindings")) { + roleBindingsStorage := rolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("rolebindings"))) + storage["rolebindings"] = rolebindingpolicybased.NewStorage(roleBindingsStorage, newRuleValidator(), p.AuthorizerRBACSuperUser) + } + if apiResourceConfigSource.ResourceEnabled(version.WithResource("clusterroles")) { + clusterRolesStorage := clusterroleetcd.NewREST(restOptionsGetter(rbac.Resource("clusterroles"))) + storage["clusterroles"] = clusterrolepolicybased.NewStorage(clusterRolesStorage, newRuleValidator(), p.AuthorizerRBACSuperUser) + } + if apiResourceConfigSource.ResourceEnabled(version.WithResource("clusterrolebindings")) { + clusterRoleBindingsStorage := clusterrolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("clusterrolebindings"))) + storage["clusterrolebindings"] = clusterrolebindingpolicybased.NewStorage(clusterRoleBindingsStorage, newRuleValidator(), p.AuthorizerRBACSuperUser) + } + return storage +}