Commit e8fb35d4 authored by deads2k's avatar deads2k

refactor resource overrides as positive logic interface

parent 3b469ff2
...@@ -36,10 +36,14 @@ import ( ...@@ -36,10 +36,14 @@ import (
"k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
apiv1 "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/apimachinery/registered" "k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/autoscaling"
autoscalingapiv1 "k8s.io/kubernetes/pkg/apis/autoscaling/v1"
"k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/batch"
batchapiv1 "k8s.io/kubernetes/pkg/apis/batch/v1"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
extensionsapiv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
"k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/apiserver"
"k8s.io/kubernetes/pkg/apiserver/authenticator" "k8s.io/kubernetes/pkg/apiserver/authenticator"
"k8s.io/kubernetes/pkg/capabilities" "k8s.io/kubernetes/pkg/capabilities"
...@@ -249,7 +253,7 @@ func Run(s *options.APIServer) error { ...@@ -249,7 +253,7 @@ func Run(s *options.APIServer) error {
glog.Fatalf("Failure to start kubelet client: %v", err) glog.Fatalf("Failure to start kubelet client: %v", err)
} }
apiGroupVersionOverrides, err := parseRuntimeConfig(s) apiResourceConfigSource, err := parseRuntimeConfig(s)
if err != nil { if err != nil {
glog.Fatalf("error in parsing runtime-config: %s", err) glog.Fatalf("error in parsing runtime-config: %s", err)
} }
...@@ -292,7 +296,7 @@ func Run(s *options.APIServer) error { ...@@ -292,7 +296,7 @@ func Run(s *options.APIServer) error {
} }
storageDestinations.AddAPIGroup("", etcdStorage) storageDestinations.AddAPIGroup("", etcdStorage)
if !apiGroupVersionOverrides["extensions/v1beta1"].Disable { if apiResourceConfigSource.AnyResourcesForVersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) {
glog.Infof("Configuring extensions/v1beta1 storage destination") glog.Infof("Configuring extensions/v1beta1 storage destination")
expGroup, err := registered.Group(extensions.GroupName) expGroup, err := registered.Group(extensions.GroupName)
if err != nil { if err != nil {
...@@ -321,7 +325,7 @@ func Run(s *options.APIServer) error { ...@@ -321,7 +325,7 @@ func Run(s *options.APIServer) error {
// autoscaling/v1/horizontalpodautoscalers is a move from extensions/v1beta1/horizontalpodautoscalers. // autoscaling/v1/horizontalpodautoscalers is a move from extensions/v1beta1/horizontalpodautoscalers.
// The storage version needs to be either extensions/v1beta1 or autoscaling/v1. // The storage version needs to be either extensions/v1beta1 or autoscaling/v1.
// Users must roll forward while using 1.2, because we will require the latter for 1.3. // Users must roll forward while using 1.2, because we will require the latter for 1.3.
if !apiGroupVersionOverrides["autoscaling/v1"].Disable { if apiResourceConfigSource.AnyResourcesForVersionEnabled(autoscalingapiv1.SchemeGroupVersion) {
glog.Infof("Configuring autoscaling/v1 storage destination") glog.Infof("Configuring autoscaling/v1 storage destination")
autoscalingGroup, err := registered.Group(autoscaling.GroupName) autoscalingGroup, err := registered.Group(autoscaling.GroupName)
if err != nil { if err != nil {
...@@ -348,7 +352,7 @@ func Run(s *options.APIServer) error { ...@@ -348,7 +352,7 @@ func Run(s *options.APIServer) error {
// version needs to be either extensions/v1beta1 or batch/v1. Users // version needs to be either extensions/v1beta1 or batch/v1. Users
// must roll forward while using 1.2, because we will require the // must roll forward while using 1.2, because we will require the
// latter for 1.3. // latter for 1.3.
if !apiGroupVersionOverrides["batch/v1"].Disable { if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv1.SchemeGroupVersion) {
glog.Infof("Configuring batch/v1 storage destination") glog.Infof("Configuring batch/v1 storage destination")
batchGroup, err := registered.Group(batch.GroupName) batchGroup, err := registered.Group(batch.GroupName)
if err != nil { if err != nil {
...@@ -464,7 +468,7 @@ func Run(s *options.APIServer) error { ...@@ -464,7 +468,7 @@ func Run(s *options.APIServer) error {
SupportsBasicAuth: len(s.BasicAuthFile) > 0, SupportsBasicAuth: len(s.BasicAuthFile) > 0,
Authorizer: authorizer, Authorizer: authorizer,
AdmissionControl: admissionController, AdmissionControl: admissionController,
APIGroupVersionOverrides: apiGroupVersionOverrides, APIResourceConfigSource: apiResourceConfigSource,
MasterServiceNamespace: s.MasterServiceNamespace, MasterServiceNamespace: s.MasterServiceNamespace,
MasterCount: s.MasterCount, MasterCount: s.MasterCount,
ExternalHost: s.ExternalHost, ExternalHost: s.ExternalHost,
...@@ -511,13 +515,24 @@ func getRuntimeConfigValue(s *options.APIServer, apiKey string, defaultValue boo ...@@ -511,13 +515,24 @@ func getRuntimeConfigValue(s *options.APIServer, apiKey string, defaultValue boo
return defaultValue return defaultValue
} }
// Parses the given runtime-config and formats it into map[string]ApiGroupVersionOverride // Parses the given runtime-config and formats it into genericapiserver.APIResourceConfigSource
func parseRuntimeConfig(s *options.APIServer) (map[string]genericapiserver.APIGroupVersionOverride, error) { func parseRuntimeConfig(s *options.APIServer) (genericapiserver.APIResourceConfigSource, error) {
v1GroupVersionString := "api/v1"
extensionsGroupVersionString := extensionsapiv1beta1.SchemeGroupVersion.String()
versionToResourceSpecifier := map[unversioned.GroupVersion]string{
apiv1.SchemeGroupVersion: v1GroupVersionString,
extensionsapiv1beta1.SchemeGroupVersion: extensionsGroupVersionString,
batchapiv1.SchemeGroupVersion: batchapiv1.SchemeGroupVersion.String(),
autoscalingapiv1.SchemeGroupVersion: autoscalingapiv1.SchemeGroupVersion.String(),
}
resourceConfig := master.DefaultAPIResourceConfigSource()
// "api/all=false" allows users to selectively enable specific api versions. // "api/all=false" allows users to selectively enable specific api versions.
disableAllAPIs := false enableAPIByDefault := true
allAPIFlagValue, ok := s.RuntimeConfig["api/all"] allAPIFlagValue, ok := s.RuntimeConfig["api/all"]
if ok && allAPIFlagValue == "false" { if ok && allAPIFlagValue == "false" {
disableAllAPIs = true enableAPIByDefault = false
} }
// "api/legacy=false" allows users to disable legacy api versions. // "api/legacy=false" allows users to disable legacy api versions.
...@@ -528,60 +543,40 @@ func parseRuntimeConfig(s *options.APIServer) (map[string]genericapiserver.APIGr ...@@ -528,60 +543,40 @@ func parseRuntimeConfig(s *options.APIServer) (map[string]genericapiserver.APIGr
} }
_ = disableLegacyAPIs // hush the compiler while we don't have legacy APIs to disable. _ = disableLegacyAPIs // hush the compiler while we don't have legacy APIs to disable.
// "api/v1={true|false} allows users to enable/disable v1 API. // "<resourceSpecifier>={true|false} allows users to enable/disable API.
// This takes preference over api/all and api/legacy, if specified. // This takes preference over api/all and api/legacy, if specified.
disableV1 := disableAllAPIs for version, resourceSpecifier := range versionToResourceSpecifier {
v1GroupVersion := "api/v1" enableVersion := getRuntimeConfigValue(s, resourceSpecifier, enableAPIByDefault)
disableV1 = !getRuntimeConfigValue(s, v1GroupVersion, !disableV1) if enableVersion {
apiGroupVersionOverrides := map[string]genericapiserver.APIGroupVersionOverride{} resourceConfig.EnableVersions(version)
if disableV1 { } else {
apiGroupVersionOverrides[v1GroupVersion] = genericapiserver.APIGroupVersionOverride{ resourceConfig.DisableVersions(version)
Disable: true,
} }
} }
// "extensions/v1beta1={true|false} allows users to enable/disable the extensions API. for key := range s.RuntimeConfig {
// This takes preference over api/all, if specified. tokens := strings.Split(key, "/")
disableExtensions := disableAllAPIs if len(tokens) != 3 {
extensionsGroupVersion := "extensions/v1beta1" continue
// TODO: Make this a loop over all group/versions when there are more of them.
disableExtensions = !getRuntimeConfigValue(s, extensionsGroupVersion, !disableExtensions)
if disableExtensions {
apiGroupVersionOverrides[extensionsGroupVersion] = genericapiserver.APIGroupVersionOverride{
Disable: true,
} }
}
disableAutoscaling := disableAllAPIs switch {
autoscalingGroupVersion := "autoscaling/v1" case strings.HasPrefix(key, extensionsGroupVersionString+"/"):
disableAutoscaling = !getRuntimeConfigValue(s, autoscalingGroupVersion, !disableAutoscaling) if !resourceConfig.AnyResourcesForVersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) {
if disableAutoscaling { return nil, fmt.Errorf("%v is disabled, you cannot configure its resources individually", extensionsapiv1beta1.SchemeGroupVersion)
apiGroupVersionOverrides[autoscalingGroupVersion] = genericapiserver.APIGroupVersionOverride{ }
Disable: true,
}
}
disableBatch := disableAllAPIs
batchGroupVersion := "batch/v1"
disableBatch = !getRuntimeConfigValue(s, batchGroupVersion, !disableBatch)
if disableBatch {
apiGroupVersionOverrides[batchGroupVersion] = genericapiserver.APIGroupVersionOverride{
Disable: true,
}
}
for key := range s.RuntimeConfig { resource := strings.TrimPrefix(key, extensionsGroupVersionString+"/")
if strings.HasPrefix(key, v1GroupVersion+"/") { if getRuntimeConfigValue(s, key, false) {
return nil, fmt.Errorf("api/v1 resources cannot be enabled/disabled individually") resourceConfig.EnableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource(resource))
} else if strings.HasPrefix(key, extensionsGroupVersion+"/") { } else {
resource := strings.TrimPrefix(key, extensionsGroupVersion+"/") resourceConfig.DisableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource(resource))
apiGroupVersionOverride := apiGroupVersionOverrides[extensionsGroupVersion]
if apiGroupVersionOverride.ResourceOverrides == nil {
apiGroupVersionOverride.ResourceOverrides = map[string]bool{}
} }
apiGroupVersionOverride.ResourceOverrides[resource] = getRuntimeConfigValue(s, key, false)
apiGroupVersionOverrides[extensionsGroupVersion] = apiGroupVersionOverride default:
// TODO enable individual resource capability for all GroupVersionResources
return nil, fmt.Errorf("%v resources cannot be enabled/disabled individually", key)
} }
} }
return apiGroupVersionOverrides, nil return resourceConfig, nil
} }
...@@ -24,8 +24,10 @@ import ( ...@@ -24,8 +24,10 @@ import (
"k8s.io/kubernetes/cmd/kube-apiserver/app/options" "k8s.io/kubernetes/cmd/kube-apiserver/app/options"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/genericapiserver" "k8s.io/kubernetes/pkg/genericapiserver"
"k8s.io/kubernetes/pkg/master"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/storage" "k8s.io/kubernetes/pkg/storage"
etcdstorage "k8s.io/kubernetes/pkg/storage/etcd" etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
...@@ -132,13 +134,15 @@ func TestUpdateEtcdOverrides(t *testing.T) { ...@@ -132,13 +134,15 @@ func TestUpdateEtcdOverrides(t *testing.T) {
func TestParseRuntimeConfig(t *testing.T) { func TestParseRuntimeConfig(t *testing.T) {
testCases := []struct { testCases := []struct {
runtimeConfig map[string]string runtimeConfig map[string]string
apiGroupVersionOverrides map[string]genericapiserver.APIGroupVersionOverride expectedAPIConfig func() *genericapiserver.ResourceConfig
err bool err bool
}{ }{
{ {
runtimeConfig: map[string]string{}, runtimeConfig: map[string]string{},
apiGroupVersionOverrides: map[string]genericapiserver.APIGroupVersionOverride{}, expectedAPIConfig: func() *genericapiserver.ResourceConfig {
return master.DefaultAPIResourceConfigSource()
},
err: false, err: false,
}, },
{ {
...@@ -146,7 +150,9 @@ func TestParseRuntimeConfig(t *testing.T) { ...@@ -146,7 +150,9 @@ func TestParseRuntimeConfig(t *testing.T) {
runtimeConfig: map[string]string{ runtimeConfig: map[string]string{
"api/v1/pods": "false", "api/v1/pods": "false",
}, },
apiGroupVersionOverrides: map[string]genericapiserver.APIGroupVersionOverride{}, expectedAPIConfig: func() *genericapiserver.ResourceConfig {
return master.DefaultAPIResourceConfigSource()
},
err: true, err: true,
}, },
{ {
...@@ -154,10 +160,10 @@ func TestParseRuntimeConfig(t *testing.T) { ...@@ -154,10 +160,10 @@ func TestParseRuntimeConfig(t *testing.T) {
runtimeConfig: map[string]string{ runtimeConfig: map[string]string{
"api/v1": "false", "api/v1": "false",
}, },
apiGroupVersionOverrides: map[string]genericapiserver.APIGroupVersionOverride{ expectedAPIConfig: func() *genericapiserver.ResourceConfig {
"api/v1": { config := master.DefaultAPIResourceConfigSource()
Disable: true, config.DisableVersions(unversioned.GroupVersion{Group: "", Version: "v1"})
}, return config
}, },
err: false, err: false,
}, },
...@@ -166,10 +172,10 @@ func TestParseRuntimeConfig(t *testing.T) { ...@@ -166,10 +172,10 @@ func TestParseRuntimeConfig(t *testing.T) {
runtimeConfig: map[string]string{ runtimeConfig: map[string]string{
"extensions/v1beta1": "false", "extensions/v1beta1": "false",
}, },
apiGroupVersionOverrides: map[string]genericapiserver.APIGroupVersionOverride{ expectedAPIConfig: func() *genericapiserver.ResourceConfig {
"extensions/v1beta1": { config := master.DefaultAPIResourceConfigSource()
Disable: true, config.DisableVersions(unversioned.GroupVersion{Group: "extensions", Version: "v1beta1"})
}, return config
}, },
err: false, err: false,
}, },
...@@ -178,28 +184,24 @@ func TestParseRuntimeConfig(t *testing.T) { ...@@ -178,28 +184,24 @@ func TestParseRuntimeConfig(t *testing.T) {
runtimeConfig: map[string]string{ runtimeConfig: map[string]string{
"extensions/v1beta1/deployments": "false", "extensions/v1beta1/deployments": "false",
}, },
apiGroupVersionOverrides: map[string]genericapiserver.APIGroupVersionOverride{ expectedAPIConfig: func() *genericapiserver.ResourceConfig {
"extensions/v1beta1": { config := master.DefaultAPIResourceConfigSource()
ResourceOverrides: map[string]bool{ config.DisableResources(unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"})
"deployments": false, return config
},
},
}, },
err: false, err: false,
}, },
{ {
// Enable deployments and disable jobs. // Enable deployments and disable jobs.
runtimeConfig: map[string]string{ runtimeConfig: map[string]string{
"extensions/v1beta1/deployments": "true", "extensions/v1beta1/anything": "true",
"extensions/v1beta1/jobs": "false", "extensions/v1beta1/jobs": "false",
}, },
apiGroupVersionOverrides: map[string]genericapiserver.APIGroupVersionOverride{ expectedAPIConfig: func() *genericapiserver.ResourceConfig {
"extensions/v1beta1": { config := master.DefaultAPIResourceConfigSource()
ResourceOverrides: map[string]bool{ config.DisableResources(unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "jobs"})
"deployments": true, config.EnableResources(unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "anything"})
"jobs": false, return config
},
},
}, },
err: false, err: false,
}, },
...@@ -208,7 +210,7 @@ func TestParseRuntimeConfig(t *testing.T) { ...@@ -208,7 +210,7 @@ func TestParseRuntimeConfig(t *testing.T) {
s := &options.APIServer{ s := &options.APIServer{
RuntimeConfig: test.runtimeConfig, RuntimeConfig: test.runtimeConfig,
} }
apiGroupVersionOverrides, err := parseRuntimeConfig(s) actualDisablers, err := parseRuntimeConfig(s)
if err == nil && test.err { if err == nil && test.err {
t.Fatalf("expected error for test: %v", test) t.Fatalf("expected error for test: %v", test)
...@@ -216,8 +218,9 @@ func TestParseRuntimeConfig(t *testing.T) { ...@@ -216,8 +218,9 @@ func TestParseRuntimeConfig(t *testing.T) {
t.Fatalf("unexpected error: %s, for test: %v", err, test) t.Fatalf("unexpected error: %s, for test: %v", err, test)
} }
if err == nil && !reflect.DeepEqual(apiGroupVersionOverrides, test.apiGroupVersionOverrides) { expectedConfig := test.expectedAPIConfig()
t.Fatalf("unexpected apiGroupVersionOverrides. Actual: %v, expected: %v", apiGroupVersionOverrides, test.apiGroupVersionOverrides) if err == nil && !reflect.DeepEqual(actualDisablers, expectedConfig) {
t.Fatalf("%v: unexpected apiResourceDisablers. Actual: %q\n expected: %q", test.runtimeConfig, actualDisablers, expectedConfig)
} }
} }
......
...@@ -164,15 +164,6 @@ func (s *StorageDestinations) Backends() []string { ...@@ -164,15 +164,6 @@ func (s *StorageDestinations) Backends() []string {
return backends.List() return backends.List()
} }
// Specifies the overrides for various API group versions.
// This can be used to enable/disable entire group versions or specific resources.
type APIGroupVersionOverride struct {
// Whether to enable or disable this group version.
Disable bool
// List of overrides for individual resources in this group version.
ResourceOverrides map[string]bool
}
// Info about an API group. // Info about an API group.
type APIGroupInfo struct { type APIGroupInfo struct {
GroupMeta apimachinery.GroupMeta GroupMeta apimachinery.GroupMeta
...@@ -218,7 +209,7 @@ type Config struct { ...@@ -218,7 +209,7 @@ type Config struct {
// Note that this is ignored if either EnableSwaggerSupport or EnableUISupport is false. // Note that this is ignored if either EnableSwaggerSupport or EnableUISupport is false.
EnableSwaggerUI bool EnableSwaggerUI bool
// Allows api group versions or specific resources to be conditionally enabled/disabled. // Allows api group versions or specific resources to be conditionally enabled/disabled.
APIGroupVersionOverrides map[string]APIGroupVersionOverride APIResourceConfigSource APIResourceConfigSource
// allow downstream consumers to disable the index route // allow downstream consumers to disable the index route
EnableIndex bool EnableIndex bool
EnableProfiling bool EnableProfiling bool
...@@ -305,25 +296,24 @@ type GenericAPIServer struct { ...@@ -305,25 +296,24 @@ type GenericAPIServer struct {
cacheTimeout time.Duration cacheTimeout time.Duration
MinRequestTimeout time.Duration MinRequestTimeout time.Duration
mux apiserver.Mux mux apiserver.Mux
MuxHelper *apiserver.MuxHelper MuxHelper *apiserver.MuxHelper
HandlerContainer *restful.Container HandlerContainer *restful.Container
RootWebService *restful.WebService RootWebService *restful.WebService
enableLogsSupport bool enableLogsSupport bool
enableUISupport bool enableUISupport bool
enableSwaggerSupport bool enableSwaggerSupport bool
enableSwaggerUI bool enableSwaggerUI bool
enableProfiling bool enableProfiling bool
enableWatchCache bool enableWatchCache bool
APIPrefix string APIPrefix string
APIGroupPrefix string APIGroupPrefix string
corsAllowedOriginList []string corsAllowedOriginList []string
authenticator authenticator.Request authenticator authenticator.Request
authorizer authorizer.Authorizer authorizer authorizer.Authorizer
AdmissionControl admission.Interface AdmissionControl admission.Interface
MasterCount int MasterCount int
ApiGroupVersionOverrides map[string]APIGroupVersionOverride RequestContextMapper api.RequestContextMapper
RequestContextMapper api.RequestContextMapper
// ExternalAddress is the address (hostname or IP and port) that should be used in // ExternalAddress is the address (hostname or IP and port) that should be used in
// external (public internet) URLs for this GenericAPIServer. // external (public internet) URLs for this GenericAPIServer.
...@@ -451,24 +441,23 @@ func New(c *Config) (*GenericAPIServer, error) { ...@@ -451,24 +441,23 @@ func New(c *Config) (*GenericAPIServer, error) {
setDefaults(c) setDefaults(c)
s := &GenericAPIServer{ s := &GenericAPIServer{
ServiceClusterIPRange: c.ServiceClusterIPRange, ServiceClusterIPRange: c.ServiceClusterIPRange,
ServiceNodePortRange: c.ServiceNodePortRange, ServiceNodePortRange: c.ServiceNodePortRange,
RootWebService: new(restful.WebService), RootWebService: new(restful.WebService),
enableLogsSupport: c.EnableLogsSupport, enableLogsSupport: c.EnableLogsSupport,
enableUISupport: c.EnableUISupport, enableUISupport: c.EnableUISupport,
enableSwaggerSupport: c.EnableSwaggerSupport, enableSwaggerSupport: c.EnableSwaggerSupport,
enableSwaggerUI: c.EnableSwaggerUI, enableSwaggerUI: c.EnableSwaggerUI,
enableProfiling: c.EnableProfiling, enableProfiling: c.EnableProfiling,
enableWatchCache: c.EnableWatchCache, enableWatchCache: c.EnableWatchCache,
APIPrefix: c.APIPrefix, APIPrefix: c.APIPrefix,
APIGroupPrefix: c.APIGroupPrefix, APIGroupPrefix: c.APIGroupPrefix,
corsAllowedOriginList: c.CorsAllowedOriginList, corsAllowedOriginList: c.CorsAllowedOriginList,
authenticator: c.Authenticator, authenticator: c.Authenticator,
authorizer: c.Authorizer, authorizer: c.Authorizer,
AdmissionControl: c.AdmissionControl, AdmissionControl: c.AdmissionControl,
ApiGroupVersionOverrides: c.APIGroupVersionOverrides, RequestContextMapper: c.RequestContextMapper,
RequestContextMapper: c.RequestContextMapper, Serializer: c.Serializer,
Serializer: c.Serializer,
cacheTimeout: c.CacheTimeout, cacheTimeout: c.CacheTimeout,
MinRequestTimeout: time.Duration(c.MinRequestTimeout) * time.Second, MinRequestTimeout: time.Duration(c.MinRequestTimeout) * time.Second,
......
...@@ -88,7 +88,6 @@ func TestNew(t *testing.T) { ...@@ -88,7 +88,6 @@ func TestNew(t *testing.T) {
assert.Equal(s.authenticator, config.Authenticator) assert.Equal(s.authenticator, config.Authenticator)
assert.Equal(s.authorizer, config.Authorizer) assert.Equal(s.authorizer, config.Authorizer)
assert.Equal(s.AdmissionControl, config.AdmissionControl) assert.Equal(s.AdmissionControl, config.AdmissionControl)
assert.Equal(s.ApiGroupVersionOverrides, config.APIGroupVersionOverrides)
assert.Equal(s.RequestContextMapper, config.RequestContextMapper) assert.Equal(s.RequestContextMapper, config.RequestContextMapper)
assert.Equal(s.cacheTimeout, config.CacheTimeout) assert.Equal(s.cacheTimeout, config.CacheTimeout)
assert.Equal(s.ExternalAddress, config.ExternalHost) assert.Equal(s.ExternalAddress, config.ExternalHost)
......
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 genericapiserver
import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/util/sets"
)
// APIResourceConfigSource is the interface to determine which versions and resources are enabled
type APIResourceConfigSource interface {
AnyVersionOfResourceEnabled(resource unversioned.GroupResource) bool
ResourceEnabled(resource unversioned.GroupVersionResource) bool
AllResourcesForVersionEnabled(version unversioned.GroupVersion) bool
AnyResourcesForVersionEnabled(version unversioned.GroupVersion) bool
}
// Specifies the overrides for various API group versions.
// This can be used to enable/disable entire group versions or specific resources.
type GroupVersionResourceConfig struct {
// Whether to enable or disable this entire group version. This dominates any enablement check.
// Enable=true means the group version is enabled, and EnabledResources/DisabledResources are considered.
// Enable=false means the group version is disabled, and EnabledResources/DisabledResources are not considered.
Enable bool
// DisabledResources lists the resources that are specifically disabled for a group/version
// DisabledResources trumps EnabledResources
DisabledResources sets.String
// EnabledResources lists the resources that should be enabled by default. This is a little
// unusual, but we need it for compatibility with old code for now. An empty set means
// enable all, a non-empty set means that all other resources are disabled.
EnabledResources sets.String
}
var _ APIResourceConfigSource = &ResourceConfig{}
type ResourceConfig struct {
GroupVersionResourceConfigs map[unversioned.GroupVersion]*GroupVersionResourceConfig
}
func NewResourceConfig() *ResourceConfig {
return &ResourceConfig{GroupVersionResourceConfigs: map[unversioned.GroupVersion]*GroupVersionResourceConfig{}}
}
func NewGroupVersionResourceConfig() *GroupVersionResourceConfig {
return &GroupVersionResourceConfig{Enable: true, DisabledResources: sets.String{}, EnabledResources: sets.String{}}
}
// DisableVersions disables the versions entirely. No resources (even those whitelisted in EnabledResources) will be enabled
func (o *ResourceConfig) DisableVersions(versions ...unversioned.GroupVersion) {
for _, version := range versions {
_, versionExists := o.GroupVersionResourceConfigs[version]
if !versionExists {
o.GroupVersionResourceConfigs[version] = NewGroupVersionResourceConfig()
}
o.GroupVersionResourceConfigs[version].Enable = false
}
}
func (o *ResourceConfig) EnableVersions(versions ...unversioned.GroupVersion) {
for _, version := range versions {
_, versionExists := o.GroupVersionResourceConfigs[version]
if !versionExists {
o.GroupVersionResourceConfigs[version] = NewGroupVersionResourceConfig()
}
o.GroupVersionResourceConfigs[version].Enable = true
}
}
func (o *ResourceConfig) DisableResources(resources ...unversioned.GroupVersionResource) {
for _, resource := range resources {
version := resource.GroupVersion()
_, versionExists := o.GroupVersionResourceConfigs[version]
if !versionExists {
o.GroupVersionResourceConfigs[version] = NewGroupVersionResourceConfig()
}
o.GroupVersionResourceConfigs[version].DisabledResources.Insert(resource.Resource)
}
}
func (o *ResourceConfig) EnableResources(resources ...unversioned.GroupVersionResource) {
for _, resource := range resources {
version := resource.GroupVersion()
_, versionExists := o.GroupVersionResourceConfigs[version]
if !versionExists {
o.GroupVersionResourceConfigs[version] = NewGroupVersionResourceConfig()
}
o.GroupVersionResourceConfigs[version].EnabledResources.Insert(resource.Resource)
o.GroupVersionResourceConfigs[version].DisabledResources.Delete(resource.Resource)
}
}
// AnyResourcesForVersionEnabled only considers matches based on exactly group/resource lexical matching. This means that
// resource renames across versions are NOT considered to be the same resource by this method. You'll need to manually check
// using the ResourceEnabled function.
func (o *ResourceConfig) AnyVersionOfResourceEnabled(resource unversioned.GroupResource) bool {
for version := range o.GroupVersionResourceConfigs {
if version.Group != resource.Group {
continue
}
if o.ResourceEnabled(version.WithResource(resource.Resource)) {
return true
}
}
return false
}
func (o *ResourceConfig) ResourceEnabled(resource unversioned.GroupVersionResource) bool {
versionOverride, versionExists := o.GroupVersionResourceConfigs[resource.GroupVersion()]
if !versionExists {
return false
}
if !versionOverride.Enable {
return false
}
if versionOverride.DisabledResources.Has(resource.Resource) {
return false
}
if len(versionOverride.EnabledResources) > 0 {
return versionOverride.EnabledResources.Has(resource.Resource)
}
return true
}
func (o *ResourceConfig) AllResourcesForVersionEnabled(version unversioned.GroupVersion) bool {
versionOverride, versionExists := o.GroupVersionResourceConfigs[version]
if !versionExists {
return false
}
if !versionOverride.Enable {
return false
}
if len(versionOverride.EnabledResources) == 0 && len(versionOverride.DisabledResources) == 0 {
return true
}
return false
}
func (o *ResourceConfig) AnyResourcesForVersionEnabled(version unversioned.GroupVersion) bool {
versionOverride, versionExists := o.GroupVersionResourceConfigs[version]
if !versionExists {
return false
}
return versionOverride.Enable
}
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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 genericapiserver
import (
"testing"
"k8s.io/kubernetes/pkg/api/unversioned"
)
func TestDisabledVersion(t *testing.T) {
g1v1 := unversioned.GroupVersion{Group: "group1", Version: "version1"}
g1v2 := unversioned.GroupVersion{Group: "group1", Version: "version2"}
g2v1 := unversioned.GroupVersion{Group: "group2", Version: "version1"}
g3v1 := unversioned.GroupVersion{Group: "group3", Version: "version1"}
resourceType := "the-resource"
disabledResourceType := "the-disabled-resource"
config := NewResourceConfig()
config.DisableVersions(g1v1)
config.EnableVersions(g1v2, g3v1)
config.EnableResources(g1v1.WithResource(resourceType), g2v1.WithResource(resourceType))
config.DisableResources(g1v2.WithResource(disabledResourceType))
expectedEnabledResources := []unversioned.GroupVersionResource{
g1v2.WithResource(resourceType),
g2v1.WithResource(resourceType),
}
expectedDisabledResources := []unversioned.GroupVersionResource{
g1v1.WithResource(resourceType), g1v1.WithResource(disabledResourceType),
g1v2.WithResource(disabledResourceType),
g2v1.WithResource(disabledResourceType),
}
for _, expectedResource := range expectedEnabledResources {
if !config.ResourceEnabled(expectedResource) {
t.Errorf("expected enabled for %v, from %v", expectedResource, config)
}
}
for _, expectedResource := range expectedDisabledResources {
if config.ResourceEnabled(expectedResource) {
t.Errorf("expected disabled for %v, from %v", expectedResource, config)
}
}
if e, a := false, config.AnyResourcesForVersionEnabled(g1v1); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := false, config.AllResourcesForVersionEnabled(g1v1); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := true, config.AnyResourcesForVersionEnabled(g1v2); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := false, config.AllResourcesForVersionEnabled(g1v2); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := true, config.AnyResourcesForVersionEnabled(g3v1); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := true, config.AllResourcesForVersionEnabled(g3v1); e != a {
t.Errorf("expected %v, got %v", e, a)
}
expectedEnabledAnyVersionResources := []unversioned.GroupResource{
{Group: "group1", Resource: resourceType},
}
expectedDisabledAnyResources := []unversioned.GroupResource{
{Group: "group1", Resource: disabledResourceType},
}
for _, expectedResource := range expectedEnabledAnyVersionResources {
if !config.AnyVersionOfResourceEnabled(expectedResource) {
t.Errorf("expected enabled for %v, from %v", expectedResource, config)
}
}
for _, expectedResource := range expectedDisabledAnyResources {
if config.AnyVersionOfResourceEnabled(expectedResource) {
t.Errorf("expected disabled for %v, from %v", expectedResource, config)
}
}
}
...@@ -95,6 +95,7 @@ func newMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *ass ...@@ -95,6 +95,7 @@ func newMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *ass
config.KubeletClient = client.FakeKubeletClient{} config.KubeletClient = client.FakeKubeletClient{}
config.APIPrefix = "/api" config.APIPrefix = "/api"
config.APIGroupPrefix = "/apis" config.APIGroupPrefix = "/apis"
config.APIResourceConfigSource = DefaultAPIResourceConfigSource()
config.ProxyDialer = func(network, addr string) (net.Conn, error) { return nil, nil } config.ProxyDialer = func(network, addr string) (net.Conn, error) { return nil, nil }
config.ProxyTLSClientConfig = &tls.Config{} config.ProxyTLSClientConfig = &tls.Config{}
...@@ -126,7 +127,6 @@ func TestNew(t *testing.T) { ...@@ -126,7 +127,6 @@ func TestNew(t *testing.T) {
assert.Equal(master.tunneler, config.Tunneler) assert.Equal(master.tunneler, config.Tunneler)
assert.Equal(master.APIPrefix, config.APIPrefix) assert.Equal(master.APIPrefix, config.APIPrefix)
assert.Equal(master.APIGroupPrefix, config.APIGroupPrefix) assert.Equal(master.APIGroupPrefix, config.APIGroupPrefix)
assert.Equal(master.ApiGroupVersionOverrides, config.APIGroupVersionOverrides)
assert.Equal(master.RequestContextMapper, config.RequestContextMapper) assert.Equal(master.RequestContextMapper, config.RequestContextMapper)
assert.Equal(master.MasterCount, config.MasterCount) assert.Equal(master.MasterCount, config.MasterCount)
assert.Equal(master.ClusterIP, config.PublicAddress) assert.Equal(master.ClusterIP, config.PublicAddress)
......
...@@ -168,13 +168,14 @@ func NewMasterConfig() *master.Config { ...@@ -168,13 +168,14 @@ func NewMasterConfig() *master.Config {
return &master.Config{ return &master.Config{
Config: &genericapiserver.Config{ Config: &genericapiserver.Config{
StorageDestinations: storageDestinations, StorageDestinations: storageDestinations,
StorageVersions: storageVersions, StorageVersions: storageVersions,
APIPrefix: "/api", APIResourceConfigSource: master.DefaultAPIResourceConfigSource(),
APIGroupPrefix: "/apis", APIPrefix: "/api",
Authorizer: apiserver.NewAlwaysAllowAuthorizer(), APIGroupPrefix: "/apis",
AdmissionControl: admit.NewAlwaysAdmit(), Authorizer: apiserver.NewAlwaysAllowAuthorizer(),
Serializer: api.Codecs, AdmissionControl: admit.NewAlwaysAdmit(),
Serializer: api.Codecs,
}, },
KubeletClient: kubeletclient.FakeKubeletClient{}, KubeletClient: kubeletclient.FakeKubeletClient{},
} }
...@@ -186,6 +187,7 @@ func NewIntegrationTestMasterConfig() *master.Config { ...@@ -186,6 +187,7 @@ func NewIntegrationTestMasterConfig() *master.Config {
masterConfig.EnableCoreControllers = true masterConfig.EnableCoreControllers = true
masterConfig.EnableIndex = true masterConfig.EnableIndex = true
masterConfig.PublicAddress = net.ParseIP("192.168.10.4") masterConfig.PublicAddress = net.ParseIP("192.168.10.4")
masterConfig.APIResourceConfigSource = master.DefaultAPIResourceConfigSource()
return masterConfig return masterConfig
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment