Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor resource overrides as positive logic interface #23067

Merged
merged 1 commit into from
Mar 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
105 changes: 50 additions & 55 deletions cmd/kube-apiserver/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,14 @@ import (
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
apiv1 "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"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"
"k8s.io/kubernetes/pkg/apis/extensions"
extensionsapiv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
"k8s.io/kubernetes/pkg/apiserver"
"k8s.io/kubernetes/pkg/apiserver/authenticator"
"k8s.io/kubernetes/pkg/capabilities"
Expand Down Expand Up @@ -249,7 +253,7 @@ func Run(s *options.APIServer) error {
glog.Fatalf("Failure to start kubelet client: %v", err)
}

apiGroupVersionOverrides, err := parseRuntimeConfig(s)
apiResourceConfigSource, err := parseRuntimeConfig(s)
if err != nil {
glog.Fatalf("error in parsing runtime-config: %s", err)
}
Expand Down Expand Up @@ -292,7 +296,7 @@ func Run(s *options.APIServer) error {
}
storageDestinations.AddAPIGroup("", etcdStorage)

if !apiGroupVersionOverrides["extensions/v1beta1"].Disable {
if apiResourceConfigSource.AnyResourcesForVersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) {
glog.Infof("Configuring extensions/v1beta1 storage destination")
expGroup, err := registered.Group(extensions.GroupName)
if err != nil {
Expand Down Expand Up @@ -321,7 +325,7 @@ func Run(s *options.APIServer) error {
// autoscaling/v1/horizontalpodautoscalers is a move from extensions/v1beta1/horizontalpodautoscalers.
// 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.
if !apiGroupVersionOverrides["autoscaling/v1"].Disable {
if apiResourceConfigSource.AnyResourcesForVersionEnabled(autoscalingapiv1.SchemeGroupVersion) {
glog.Infof("Configuring autoscaling/v1 storage destination")
autoscalingGroup, err := registered.Group(autoscaling.GroupName)
if err != nil {
Expand All @@ -348,7 +352,7 @@ func Run(s *options.APIServer) error {
// version needs to be either extensions/v1beta1 or batch/v1. Users
// must roll forward while using 1.2, because we will require the
// latter for 1.3.
if !apiGroupVersionOverrides["batch/v1"].Disable {
if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv1.SchemeGroupVersion) {
glog.Infof("Configuring batch/v1 storage destination")
batchGroup, err := registered.Group(batch.GroupName)
if err != nil {
Expand Down Expand Up @@ -464,7 +468,7 @@ func Run(s *options.APIServer) error {
SupportsBasicAuth: len(s.BasicAuthFile) > 0,
Authorizer: authorizer,
AdmissionControl: admissionController,
APIGroupVersionOverrides: apiGroupVersionOverrides,
APIResourceConfigSource: apiResourceConfigSource,
MasterServiceNamespace: s.MasterServiceNamespace,
MasterCount: s.MasterCount,
ExternalHost: s.ExternalHost,
Expand Down Expand Up @@ -511,13 +515,24 @@ func getRuntimeConfigValue(s *options.APIServer, apiKey string, defaultValue boo
return defaultValue
}

// Parses the given runtime-config and formats it into map[string]ApiGroupVersionOverride
func parseRuntimeConfig(s *options.APIServer) (map[string]genericapiserver.APIGroupVersionOverride, error) {
// Parses the given runtime-config and formats it into genericapiserver.APIResourceConfigSource
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.
disableAllAPIs := false
enableAPIByDefault := true
allAPIFlagValue, ok := s.RuntimeConfig["api/all"]
if ok && allAPIFlagValue == "false" {
disableAllAPIs = true
enableAPIByDefault = false
}

// "api/legacy=false" allows users to disable legacy api versions.
Expand All @@ -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.

// "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.
disableV1 := disableAllAPIs
v1GroupVersion := "api/v1"
disableV1 = !getRuntimeConfigValue(s, v1GroupVersion, !disableV1)
apiGroupVersionOverrides := map[string]genericapiserver.APIGroupVersionOverride{}
if disableV1 {
apiGroupVersionOverrides[v1GroupVersion] = genericapiserver.APIGroupVersionOverride{
Disable: true,
for version, resourceSpecifier := range versionToResourceSpecifier {
enableVersion := getRuntimeConfigValue(s, resourceSpecifier, enableAPIByDefault)
if enableVersion {
resourceConfig.EnableVersions(version)
} else {
resourceConfig.DisableVersions(version)
}
}

// "extensions/v1beta1={true|false} allows users to enable/disable the extensions API.
// This takes preference over api/all, if specified.
disableExtensions := disableAllAPIs
extensionsGroupVersion := "extensions/v1beta1"
// 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,
for key := range s.RuntimeConfig {
tokens := strings.Split(key, "/")
if len(tokens) != 3 {
continue
}
}

disableAutoscaling := disableAllAPIs
autoscalingGroupVersion := "autoscaling/v1"
disableAutoscaling = !getRuntimeConfigValue(s, autoscalingGroupVersion, !disableAutoscaling)
if disableAutoscaling {
apiGroupVersionOverrides[autoscalingGroupVersion] = genericapiserver.APIGroupVersionOverride{
Disable: true,
}
}
disableBatch := disableAllAPIs
batchGroupVersion := "batch/v1"
disableBatch = !getRuntimeConfigValue(s, batchGroupVersion, !disableBatch)
if disableBatch {
apiGroupVersionOverrides[batchGroupVersion] = genericapiserver.APIGroupVersionOverride{
Disable: true,
}
}
switch {
case strings.HasPrefix(key, extensionsGroupVersionString+"/"):
if !resourceConfig.AnyResourcesForVersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) {
return nil, fmt.Errorf("%v is disabled, you cannot configure its resources individually", extensionsapiv1beta1.SchemeGroupVersion)
}

for key := range s.RuntimeConfig {
if strings.HasPrefix(key, v1GroupVersion+"/") {
return nil, fmt.Errorf("api/v1 resources cannot be enabled/disabled individually")
} else if strings.HasPrefix(key, extensionsGroupVersion+"/") {
resource := strings.TrimPrefix(key, extensionsGroupVersion+"/")

apiGroupVersionOverride := apiGroupVersionOverrides[extensionsGroupVersion]
if apiGroupVersionOverride.ResourceOverrides == nil {
apiGroupVersionOverride.ResourceOverrides = map[string]bool{}
resource := strings.TrimPrefix(key, extensionsGroupVersionString+"/")
if getRuntimeConfigValue(s, key, false) {
resourceConfig.EnableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource(resource))
} else {
resourceConfig.DisableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource(resource))
}
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
}
67 changes: 35 additions & 32 deletions cmd/kube-apiserver/app/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import (

"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/genericapiserver"
"k8s.io/kubernetes/pkg/master"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/storage"
etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
Expand Down Expand Up @@ -132,32 +134,36 @@ func TestUpdateEtcdOverrides(t *testing.T) {

func TestParseRuntimeConfig(t *testing.T) {
testCases := []struct {
runtimeConfig map[string]string
apiGroupVersionOverrides map[string]genericapiserver.APIGroupVersionOverride
err bool
runtimeConfig map[string]string
expectedAPIConfig func() *genericapiserver.ResourceConfig
err bool
}{
{
runtimeConfig: map[string]string{},
apiGroupVersionOverrides: map[string]genericapiserver.APIGroupVersionOverride{},
runtimeConfig: map[string]string{},
expectedAPIConfig: func() *genericapiserver.ResourceConfig {
return master.DefaultAPIResourceConfigSource()
},
err: false,
},
{
// Cannot override v1 resources.
runtimeConfig: map[string]string{
"api/v1/pods": "false",
},
apiGroupVersionOverrides: map[string]genericapiserver.APIGroupVersionOverride{},
expectedAPIConfig: func() *genericapiserver.ResourceConfig {
return master.DefaultAPIResourceConfigSource()
},
err: true,
},
{
// Disable v1.
runtimeConfig: map[string]string{
"api/v1": "false",
},
apiGroupVersionOverrides: map[string]genericapiserver.APIGroupVersionOverride{
"api/v1": {
Disable: true,
},
expectedAPIConfig: func() *genericapiserver.ResourceConfig {
config := master.DefaultAPIResourceConfigSource()
config.DisableVersions(unversioned.GroupVersion{Group: "", Version: "v1"})
return config
},
err: false,
},
Expand All @@ -166,10 +172,10 @@ func TestParseRuntimeConfig(t *testing.T) {
runtimeConfig: map[string]string{
"extensions/v1beta1": "false",
},
apiGroupVersionOverrides: map[string]genericapiserver.APIGroupVersionOverride{
"extensions/v1beta1": {
Disable: true,
},
expectedAPIConfig: func() *genericapiserver.ResourceConfig {
config := master.DefaultAPIResourceConfigSource()
config.DisableVersions(unversioned.GroupVersion{Group: "extensions", Version: "v1beta1"})
return config
},
err: false,
},
Expand All @@ -178,28 +184,24 @@ func TestParseRuntimeConfig(t *testing.T) {
runtimeConfig: map[string]string{
"extensions/v1beta1/deployments": "false",
},
apiGroupVersionOverrides: map[string]genericapiserver.APIGroupVersionOverride{
"extensions/v1beta1": {
ResourceOverrides: map[string]bool{
"deployments": false,
},
},
expectedAPIConfig: func() *genericapiserver.ResourceConfig {
config := master.DefaultAPIResourceConfigSource()
config.DisableResources(unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"})
return config
},
err: false,
},
{
// Enable deployments and disable jobs.
runtimeConfig: map[string]string{
"extensions/v1beta1/deployments": "true",
"extensions/v1beta1/jobs": "false",
"extensions/v1beta1/anything": "true",
"extensions/v1beta1/jobs": "false",
},
apiGroupVersionOverrides: map[string]genericapiserver.APIGroupVersionOverride{
"extensions/v1beta1": {
ResourceOverrides: map[string]bool{
"deployments": true,
"jobs": false,
},
},
expectedAPIConfig: func() *genericapiserver.ResourceConfig {
config := master.DefaultAPIResourceConfigSource()
config.DisableResources(unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "jobs"})
config.EnableResources(unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "anything"})
return config
},
err: false,
},
Expand All @@ -208,16 +210,17 @@ func TestParseRuntimeConfig(t *testing.T) {
s := &options.APIServer{
RuntimeConfig: test.runtimeConfig,
}
apiGroupVersionOverrides, err := parseRuntimeConfig(s)
actualDisablers, err := parseRuntimeConfig(s)

if err == nil && test.err {
t.Fatalf("expected error for test: %v", test)
} else if err != nil && !test.err {
t.Fatalf("unexpected error: %s, for test: %v", err, test)
}

if err == nil && !reflect.DeepEqual(apiGroupVersionOverrides, test.apiGroupVersionOverrides) {
t.Fatalf("unexpected apiGroupVersionOverrides. Actual: %v, expected: %v", apiGroupVersionOverrides, test.apiGroupVersionOverrides)
expectedConfig := test.expectedAPIConfig()
if err == nil && !reflect.DeepEqual(actualDisablers, expectedConfig) {
t.Fatalf("%v: unexpected apiResourceDisablers. Actual: %q\n expected: %q", test.runtimeConfig, actualDisablers, expectedConfig)
}
}

Expand Down