From e8fb6d1c4775889e682bec3f83a243a5a2b1724a Mon Sep 17 00:00:00 2001 From: nikhiljindal Date: Mon, 27 Feb 2017 21:55:28 -0800 Subject: [PATCH] Updating federation-apiserver to support runtime config and using it to disable batch and autoscaling groups --- .../federation-apiserver/app/autoscaling.go | 24 +++++-- .../cmd/federation-apiserver/app/batch.go | 24 +++++-- .../cmd/federation-apiserver/app/core.go | 65 ++++++++++++++----- .../federation-apiserver/app/extensions.go | 63 ++++++++++++------ .../federation-apiserver/app/federation.go | 29 ++++++--- .../cmd/federation-apiserver/app/install.go | 55 ++++++++++++++++ .../cmd/federation-apiserver/app/server.go | 44 ++++++++++--- 7 files changed, 235 insertions(+), 69 deletions(-) create mode 100644 federation/cmd/federation-apiserver/app/install.go diff --git a/federation/cmd/federation-apiserver/app/autoscaling.go b/federation/cmd/federation-apiserver/app/autoscaling.go index 6d91fd8ff50..ed147f830bb 100644 --- a/federation/cmd/federation-apiserver/app/autoscaling.go +++ b/federation/cmd/federation-apiserver/app/autoscaling.go @@ -21,24 +21,34 @@ import ( "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" genericapiserver "k8s.io/apiserver/pkg/server" + "k8s.io/apiserver/pkg/server/storage" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/autoscaling" _ "k8s.io/kubernetes/pkg/apis/autoscaling/install" + autoscalingv1 "k8s.io/kubernetes/pkg/apis/autoscaling/v1" hpastorage "k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/storage" ) -func installAutoscalingAPIs(g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter) { - hpaStorage, hpaStatusStorage := hpastorage.NewREST(optsGetter) - - autoscalingResources := map[string]rest.Storage{ - "horizontalpodautoscalers": hpaStorage, - "horizontalpodautoscalers/status": hpaStatusStorage, +func installAutoscalingAPIs(g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter, apiResourceConfigSource storage.APIResourceConfigSource) { + hpaStorageFn := func() map[string]rest.Storage { + hpaStorage, hpaStatusStorage := hpastorage.NewREST(optsGetter) + return map[string]rest.Storage{ + "horizontalpodautoscalers": hpaStorage, + "horizontalpodautoscalers/status": hpaStatusStorage, + } + } + resourcesStorageMap := map[string]getResourcesStorageFunc{ + "horizontalpodautoscalers": hpaStorageFn, + } + shouldInstallGroup, resources := enabledResources(autoscalingv1.SchemeGroupVersion, resourcesStorageMap, apiResourceConfigSource) + if !shouldInstallGroup { + return } autoscalingGroupMeta := api.Registry.GroupOrDie(autoscaling.GroupName) apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *autoscalingGroupMeta, VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ - "v1": autoscalingResources, + "v1": resources, }, OptionsExternalVersion: &api.Registry.GroupOrDie(api.GroupName).GroupVersion, Scheme: api.Scheme, diff --git a/federation/cmd/federation-apiserver/app/batch.go b/federation/cmd/federation-apiserver/app/batch.go index e9d1f6acc56..5076ca023df 100644 --- a/federation/cmd/federation-apiserver/app/batch.go +++ b/federation/cmd/federation-apiserver/app/batch.go @@ -21,24 +21,34 @@ import ( "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" genericapiserver "k8s.io/apiserver/pkg/server" + "k8s.io/apiserver/pkg/server/storage" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/batch" _ "k8s.io/kubernetes/pkg/apis/batch/install" + batchv1 "k8s.io/kubernetes/pkg/apis/batch/v1" jobstorage "k8s.io/kubernetes/pkg/registry/batch/job/storage" ) -func installBatchAPIs(g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter) { - jobStorage := jobstorage.NewStorage(optsGetter) - - batchResources := map[string]rest.Storage{ - "jobs": jobStorage.Job, - "jobs/status": jobStorage.Status, +func installBatchAPIs(g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter, apiResourceConfigSource storage.APIResourceConfigSource) { + jobsStorageFn := func() map[string]rest.Storage { + jobStorage := jobstorage.NewStorage(optsGetter) + return map[string]rest.Storage{ + "jobs": jobStorage.Job, + "jobs/status": jobStorage.Status, + } + } + resourcesStorageMap := map[string]getResourcesStorageFunc{ + "jobs": jobsStorageFn, + } + shouldInstallGroup, resources := enabledResources(batchv1.SchemeGroupVersion, resourcesStorageMap, apiResourceConfigSource) + if !shouldInstallGroup { + return } batchGroupMeta := api.Registry.GroupOrDie(batch.GroupName) apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *batchGroupMeta, VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ - "v1": batchResources, + "v1": resources, }, OptionsExternalVersion: &api.Registry.GroupOrDie(api.GroupName).GroupVersion, Scheme: api.Scheme, diff --git a/federation/cmd/federation-apiserver/app/core.go b/federation/cmd/federation-apiserver/app/core.go index 9fa60baf67f..6282530f8a6 100644 --- a/federation/cmd/federation-apiserver/app/core.go +++ b/federation/cmd/federation-apiserver/app/core.go @@ -29,9 +29,10 @@ import ( "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" genericapiserver "k8s.io/apiserver/pkg/server" + "k8s.io/apiserver/pkg/server/storage" "k8s.io/kubernetes/federation/apis/core" _ "k8s.io/kubernetes/federation/apis/core/install" - "k8s.io/kubernetes/federation/apis/core/v1" + corev1 "k8s.io/kubernetes/federation/apis/core/v1" "k8s.io/kubernetes/federation/cmd/federation-apiserver/app/options" "k8s.io/kubernetes/pkg/api" configmapstore "k8s.io/kubernetes/pkg/registry/core/configmap/storage" @@ -41,28 +42,56 @@ import ( servicestore "k8s.io/kubernetes/pkg/registry/core/service/storage" ) -func installCoreAPIs(s *options.ServerRunOptions, g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter) { - serviceStore, serviceStatusStore := servicestore.NewREST(optsGetter) - namespaceStore, namespaceStatusStore, namespaceFinalizeStore := namespacestore.NewREST(optsGetter) - secretStore := secretstore.NewREST(optsGetter) - configMapStore := configmapstore.NewREST(optsGetter) - eventStore := eventstore.NewREST(optsGetter, uint64(s.EventTTL.Seconds())) - - coreResources := map[string]rest.Storage{ - "secrets": secretStore, - "services": serviceStore, - "services/status": serviceStatusStore, - "namespaces": namespaceStore, - "namespaces/status": namespaceStatusStore, - "namespaces/finalize": namespaceFinalizeStore, - "events": eventStore, - "configmaps": configMapStore, +func installCoreAPIs(s *options.ServerRunOptions, g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter, apiResourceConfigSource storage.APIResourceConfigSource) { + servicesStorageFn := func() map[string]rest.Storage { + serviceStore, serviceStatusStore := servicestore.NewREST(optsGetter) + return map[string]rest.Storage{ + "services": serviceStore, + "services/status": serviceStatusStore, + } + } + namespacesStorageFn := func() map[string]rest.Storage { + namespaceStore, namespaceStatusStore, namespaceFinalizeStore := namespacestore.NewREST(optsGetter) + return map[string]rest.Storage{ + "namespaces": namespaceStore, + "namespaces/status": namespaceStatusStore, + "namespaces/finalize": namespaceFinalizeStore, + } + } + secretsStorageFn := func() map[string]rest.Storage { + secretStore := secretstore.NewREST(optsGetter) + return map[string]rest.Storage{ + "secrets": secretStore, + } + } + configmapsStorageFn := func() map[string]rest.Storage { + configMapStore := configmapstore.NewREST(optsGetter) + return map[string]rest.Storage{ + "configmaps": configMapStore, + } + } + eventsStorageFn := func() map[string]rest.Storage { + eventStore := eventstore.NewREST(optsGetter, uint64(s.EventTTL.Seconds())) + return map[string]rest.Storage{ + "events": eventStore, + } + } + resourcesStorageMap := map[string]getResourcesStorageFunc{ + "services": servicesStorageFn, + "namespaces": namespacesStorageFn, + "secrets": secretsStorageFn, + "configmaps": configmapsStorageFn, + "events": eventsStorageFn, + } + shouldInstallGroup, resources := enabledResources(corev1.SchemeGroupVersion, resourcesStorageMap, apiResourceConfigSource) + if !shouldInstallGroup { + return } coreGroupMeta := api.Registry.GroupOrDie(core.GroupName) apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *coreGroupMeta, VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ - v1.SchemeGroupVersion.Version: coreResources, + corev1.SchemeGroupVersion.Version: resources, }, OptionsExternalVersion: &api.Registry.GroupOrDie(core.GroupName).GroupVersion, Scheme: core.Scheme, diff --git a/federation/cmd/federation-apiserver/app/extensions.go b/federation/cmd/federation-apiserver/app/extensions.go index 876c8f6b800..292979ae50b 100644 --- a/federation/cmd/federation-apiserver/app/extensions.go +++ b/federation/cmd/federation-apiserver/app/extensions.go @@ -21,39 +21,64 @@ import ( "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" genericapiserver "k8s.io/apiserver/pkg/server" + "k8s.io/apiserver/pkg/server/storage" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/extensions" _ "k8s.io/kubernetes/pkg/apis/extensions/install" + extensionsv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" daemonsetstore "k8s.io/kubernetes/pkg/registry/extensions/daemonset/storage" deploymentstore "k8s.io/kubernetes/pkg/registry/extensions/deployment/storage" ingressstore "k8s.io/kubernetes/pkg/registry/extensions/ingress/storage" replicasetstore "k8s.io/kubernetes/pkg/registry/extensions/replicaset/storage" ) -func installExtensionsAPIs(g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter) { - replicaSetStorage := replicasetstore.NewStorage(optsGetter) - deploymentStorage := deploymentstore.NewStorage(optsGetter) - ingressStorage, ingressStatusStorage := ingressstore.NewREST(optsGetter) - daemonSetStorage, daemonSetStatusStorage := daemonsetstore.NewREST(optsGetter) - - extensionsResources := map[string]rest.Storage{ - "replicasets": replicaSetStorage.ReplicaSet, - "replicasets/status": replicaSetStorage.Status, - "replicasets/scale": replicaSetStorage.Scale, - "ingresses": ingressStorage, - "ingresses/status": ingressStatusStorage, - "daemonsets": daemonSetStorage, - "daemonsets/status": daemonSetStatusStorage, - "deployments": deploymentStorage.Deployment, - "deployments/status": deploymentStorage.Status, - "deployments/scale": deploymentStorage.Scale, - "deployments/rollback": deploymentStorage.Rollback, +func installExtensionsAPIs(g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter, apiResourceConfigSource storage.APIResourceConfigSource) { + replicasetsStorageFn := func() map[string]rest.Storage { + replicaSetStorage := replicasetstore.NewStorage(optsGetter) + return map[string]rest.Storage{ + "replicasets": replicaSetStorage.ReplicaSet, + "replicasets/status": replicaSetStorage.Status, + "replicasets/scale": replicaSetStorage.Scale, + } + } + deploymentsStorageFn := func() map[string]rest.Storage { + deploymentStorage := deploymentstore.NewStorage(optsGetter) + return map[string]rest.Storage{ + "deployments": deploymentStorage.Deployment, + "deployments/status": deploymentStorage.Status, + "deployments/scale": deploymentStorage.Scale, + "deployments/rollback": deploymentStorage.Rollback, + } + } + ingressesStorageFn := func() map[string]rest.Storage { + ingressStorage, ingressStatusStorage := ingressstore.NewREST(optsGetter) + return map[string]rest.Storage{ + "ingresses": ingressStorage, + "ingresses/status": ingressStatusStorage, + } + } + daemonsetsStorageFn := func() map[string]rest.Storage { + daemonSetStorage, daemonSetStatusStorage := daemonsetstore.NewREST(optsGetter) + return map[string]rest.Storage{ + "daemonsets": daemonSetStorage, + "daemonsets/status": daemonSetStatusStorage, + } + } + resourcesStorageMap := map[string]getResourcesStorageFunc{ + "replicasets": replicasetsStorageFn, + "deployments": deploymentsStorageFn, + "ingresses": ingressesStorageFn, + "daemonsets": daemonsetsStorageFn, + } + shouldInstallGroup, resources := enabledResources(extensionsv1beta1.SchemeGroupVersion, resourcesStorageMap, apiResourceConfigSource) + if !shouldInstallGroup { + return } extensionsGroupMeta := api.Registry.GroupOrDie(extensions.GroupName) apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *extensionsGroupMeta, VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ - "v1beta1": extensionsResources, + "v1beta1": resources, }, OptionsExternalVersion: &api.Registry.GroupOrDie(api.GroupName).GroupVersion, Scheme: api.Scheme, diff --git a/federation/cmd/federation-apiserver/app/federation.go b/federation/cmd/federation-apiserver/app/federation.go index 38ed7ead593..4870ce5fe41 100644 --- a/federation/cmd/federation-apiserver/app/federation.go +++ b/federation/cmd/federation-apiserver/app/federation.go @@ -22,24 +22,35 @@ import ( "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" genericapiserver "k8s.io/apiserver/pkg/server" + "k8s.io/apiserver/pkg/server/storage" "k8s.io/kubernetes/federation/apis/federation" - "k8s.io/kubernetes/pkg/api" - _ "k8s.io/kubernetes/federation/apis/federation/install" + fedv1beta1 "k8s.io/kubernetes/federation/apis/federation/v1beta1" clusteretcd "k8s.io/kubernetes/federation/registry/cluster/etcd" + "k8s.io/kubernetes/pkg/api" ) -func installFederationAPIs(g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter) { - clusterStorage, clusterStatusStorage := clusteretcd.NewREST(optsGetter) - federationResources := map[string]rest.Storage{ - "clusters": clusterStorage, - "clusters/status": clusterStatusStorage, +func installFederationAPIs(g *genericapiserver.GenericAPIServer, optsGetter generic.RESTOptionsGetter, apiResourceConfigSource storage.APIResourceConfigSource) { + groupName := federation.GroupName + clustersStorageFn := func() map[string]rest.Storage { + clusterStorage, clusterStatusStorage := clusteretcd.NewREST(optsGetter) + return map[string]rest.Storage{ + "clusters": clusterStorage, + "clusters/status": clusterStatusStorage, + } } - federationGroupMeta := api.Registry.GroupOrDie(federation.GroupName) + resourcesStorageMap := map[string]getResourcesStorageFunc{ + "clusters": clustersStorageFn, + } + shouldInstallGroup, resources := enabledResources(fedv1beta1.SchemeGroupVersion, resourcesStorageMap, apiResourceConfigSource) + if !shouldInstallGroup { + return + } + federationGroupMeta := api.Registry.GroupOrDie(groupName) apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *federationGroupMeta, VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ - "v1beta1": federationResources, + "v1beta1": resources, }, OptionsExternalVersion: &api.Registry.GroupOrDie(api.GroupName).GroupVersion, Scheme: api.Scheme, diff --git a/federation/cmd/federation-apiserver/app/install.go b/federation/cmd/federation-apiserver/app/install.go new file mode 100644 index 00000000000..4e75a2df1a4 --- /dev/null +++ b/federation/cmd/federation-apiserver/app/install.go @@ -0,0 +1,55 @@ +/* +Copyright 2017 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 app + +import ( + "github.com/golang/glog" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apiserver/pkg/registry/rest" + "k8s.io/apiserver/pkg/server/storage" +) + +// Function to get a map of resources and the corresponding storages. +type getResourcesStorageFunc func() map[string]rest.Storage + +// Filters the resources from the given resources storage map to those that are enabled in the given apiResourceConfigSource. +// resourcesStorageMap is expected to contain all resources in a group version. +// Returns false if none of the resources are enabled and hence the whole group version should be disabled. +func enabledResources(groupVersion schema.GroupVersion, resourcesStorageMap map[string]getResourcesStorageFunc, apiResourceConfigSource storage.APIResourceConfigSource) (bool, map[string]rest.Storage) { + enabledResources := map[string]rest.Storage{} + groupName := groupVersion.Group + if !apiResourceConfigSource.AnyResourcesForGroupEnabled(groupName) { + glog.V(1).Infof("Skipping disabled API group %q", groupName) + return false, enabledResources + } + for resource, fn := range resourcesStorageMap { + if apiResourceConfigSource.ResourceEnabled(groupVersion.WithResource(resource)) { + resources := fn() + for k, v := range resources { + enabledResources[k] = v + } + } else { + glog.V(1).Infof("Skipping disabled resource %s in API group %q", resource, groupName) + } + } + if len(enabledResources) == 0 { + glog.V(1).Infof("Skipping API group %q since there is no enabled resource", groupName) + return false, enabledResources + } + return true, enabledResources +} diff --git a/federation/cmd/federation-apiserver/app/server.go b/federation/cmd/federation-apiserver/app/server.go index 0af1beff323..be6e37502c5 100644 --- a/federation/cmd/federation-apiserver/app/server.go +++ b/federation/cmd/federation-apiserver/app/server.go @@ -38,8 +38,11 @@ import ( genericapiserver "k8s.io/apiserver/pkg/server" "k8s.io/apiserver/pkg/server/filters" serverstorage "k8s.io/apiserver/pkg/server/storage" + federationv1beta1 "k8s.io/kubernetes/federation/apis/federation/v1beta1" "k8s.io/kubernetes/federation/cmd/federation-apiserver/app/options" "k8s.io/kubernetes/pkg/api" + apiv1 "k8s.io/kubernetes/pkg/api/v1" + extensionsapiv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" "k8s.io/kubernetes/pkg/generated/openapi" @@ -124,8 +127,7 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error { return err } - // TODO: register cluster federation resources here. - resourceConfig := serverstorage.NewResourceConfig() + resourceConfig := defaultResourceConfig() if s.Etcd.StorageConfig.DeserializationCacheSize == 0 { // When size of cache is not explicitly set, set it to 50000 @@ -230,13 +232,12 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error { routes.UIRedirect{}.Install(m.FallThroughHandler) routes.Logs{}.Install(m.HandlerContainer) - installFederationAPIs(m, genericConfig.RESTOptionsGetter) - installCoreAPIs(s, m, genericConfig.RESTOptionsGetter) - installExtensionsAPIs(m, genericConfig.RESTOptionsGetter) - // Disable half-baked APIs for 1.6. - // TODO: Uncomment this once 1.6 is released. - // installBatchAPIs(m, genericConfig.RESTOptionsGetter) - // installAutoscalingAPIs(m, genericConfig.RESTOptionsGetter) + apiResourceConfigSource := storageFactory.APIResourceConfigSource + installFederationAPIs(m, genericConfig.RESTOptionsGetter, apiResourceConfigSource) + installCoreAPIs(s, m, genericConfig.RESTOptionsGetter, apiResourceConfigSource) + installExtensionsAPIs(m, genericConfig.RESTOptionsGetter, apiResourceConfigSource) + installBatchAPIs(m, genericConfig.RESTOptionsGetter, apiResourceConfigSource) + installAutoscalingAPIs(m, genericConfig.RESTOptionsGetter, apiResourceConfigSource) // run the insecure server now if insecureServingOptions != nil { @@ -253,6 +254,31 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error { return err } +func defaultResourceConfig() *serverstorage.ResourceConfig { + rc := serverstorage.NewResourceConfig() + + rc.EnableVersions( + federationv1beta1.SchemeGroupVersion, + ) + + // All core resources except these are disabled by default. + rc.EnableResources( + apiv1.SchemeGroupVersion.WithResource("secrets"), + apiv1.SchemeGroupVersion.WithResource("services"), + apiv1.SchemeGroupVersion.WithResource("namespaces"), + apiv1.SchemeGroupVersion.WithResource("events"), + apiv1.SchemeGroupVersion.WithResource("configmaps"), + ) + // All extension resources except these are disabled by default. + rc.EnableResources( + extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"), + extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"), + extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"), + extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"), + ) + return rc +} + // PostProcessSpec adds removed definitions for backward compatibility func postProcessOpenAPISpecForBackwardCompatibility(s *spec.Swagger) (*spec.Swagger, error) { compatibilityMap := map[string]string{