Commit 7bcc4a67 authored by nikhiljindal's avatar nikhiljindal

Allowing runtimeConfig to support enabling/disabling specific extension resources

parent 5174ca21
...@@ -408,29 +408,10 @@ func (s *APIServer) Run(_ []string) error { ...@@ -408,29 +408,10 @@ func (s *APIServer) Run(_ []string) error {
glog.Fatalf("Failure to start kubelet client: %v", err) glog.Fatalf("Failure to start kubelet client: %v", err)
} }
// "api/all=false" allows users to selectively enable specific api versions. apiGroupVersionOverrides, err := s.parseRuntimeConfig()
disableAllAPIs := false if err != nil {
allAPIFlagValue, ok := s.RuntimeConfig["api/all"] glog.Fatalf("error in parsing runtime-config: %s", err)
if ok && allAPIFlagValue == "false" {
disableAllAPIs = true
}
// "api/legacy=false" allows users to disable legacy api versions.
disableLegacyAPIs := false
legacyAPIFlagValue, ok := s.RuntimeConfig["api/legacy"]
if ok && legacyAPIFlagValue == "false" {
disableLegacyAPIs = true
} }
_ = disableLegacyAPIs // hush the compiler while we don't have legacy APIs to disable.
// "api/v1={true|false} allows users to enable/disable v1 API.
// This takes preference over api/all and api/legacy, if specified.
disableV1 := disableAllAPIs
disableV1 = !s.getRuntimeConfigValue("api/v1", !disableV1)
// "extensions/v1beta1={true|false} allows users to enable/disable the experimental API.
// This takes preference over api/all, if specified.
enableExp := s.getRuntimeConfigValue("extensions/v1beta1", false)
clientConfig := &client.Config{ clientConfig := &client.Config{
Host: net.JoinHostPort(s.InsecureBindAddress.String(), strconv.Itoa(s.InsecurePort)), Host: net.JoinHostPort(s.InsecureBindAddress.String(), strconv.Itoa(s.InsecurePort)),
...@@ -458,17 +439,17 @@ func (s *APIServer) Run(_ []string) error { ...@@ -458,17 +439,17 @@ func (s *APIServer) Run(_ []string) error {
} }
storageDestinations.AddAPIGroup("", etcdStorage) storageDestinations.AddAPIGroup("", etcdStorage)
if enableExp { if !apiGroupVersionOverrides["extensions/v1beta1"].Disable {
expGroup, err := latest.Group("extensions") expGroup, err := latest.Group("extensions")
if err != nil { if err != nil {
glog.Fatalf("Experimental API is enabled in runtime config, but not enabled in the environment variable KUBE_API_VERSIONS. Error: %v", err) glog.Fatalf("Extensions API is enabled in runtime config, but not enabled in the environment variable KUBE_API_VERSIONS. Error: %v", err)
} }
if _, found := storageVersions[expGroup.Group]; !found { if _, found := storageVersions[expGroup.Group]; !found {
glog.Fatalf("Couldn't find the storage version for group: %q in storageVersions: %v", expGroup.Group, storageVersions) glog.Fatalf("Couldn't find the storage version for group: %q in storageVersions: %v", expGroup.Group, storageVersions)
} }
expEtcdStorage, err := newEtcd(s.EtcdConfigFile, s.EtcdServerList, expGroup.InterfacesFor, storageVersions[expGroup.Group], s.EtcdPathPrefix) expEtcdStorage, err := newEtcd(s.EtcdConfigFile, s.EtcdServerList, expGroup.InterfacesFor, storageVersions[expGroup.Group], s.EtcdPathPrefix)
if err != nil { if err != nil {
glog.Fatalf("Invalid experimental storage version or misconfigured etcd: %v", err) glog.Fatalf("Invalid extensions storage version or misconfigured etcd: %v", err)
} }
storageDestinations.AddAPIGroup("extensions", expEtcdStorage) storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
} }
...@@ -558,8 +539,7 @@ func (s *APIServer) Run(_ []string) error { ...@@ -558,8 +539,7 @@ func (s *APIServer) Run(_ []string) error {
SupportsBasicAuth: len(s.BasicAuthFile) > 0, SupportsBasicAuth: len(s.BasicAuthFile) > 0,
Authorizer: authorizer, Authorizer: authorizer,
AdmissionControl: admissionController, AdmissionControl: admissionController,
DisableV1: disableV1, APIGroupVersionOverrides: apiGroupVersionOverrides,
EnableExp: enableExp,
MasterServiceNamespace: s.MasterServiceNamespace, MasterServiceNamespace: s.MasterServiceNamespace,
ClusterName: s.ClusterName, ClusterName: s.ClusterName,
ExternalHost: s.ExternalHost, ExternalHost: s.ExternalHost,
...@@ -680,3 +660,61 @@ func (s *APIServer) getRuntimeConfigValue(apiKey string, defaultValue bool) bool ...@@ -680,3 +660,61 @@ func (s *APIServer) getRuntimeConfigValue(apiKey string, defaultValue bool) bool
} }
return defaultValue return defaultValue
} }
// Parses the given runtime-config and formats it into map[string]ApiGroupVersionOverride
func (s *APIServer) parseRuntimeConfig() (map[string]master.APIGroupVersionOverride, error) {
// "api/all=false" allows users to selectively enable specific api versions.
disableAllAPIs := false
allAPIFlagValue, ok := s.RuntimeConfig["api/all"]
if ok && allAPIFlagValue == "false" {
disableAllAPIs = true
}
// "api/legacy=false" allows users to disable legacy api versions.
disableLegacyAPIs := false
legacyAPIFlagValue, ok := s.RuntimeConfig["api/legacy"]
if ok && legacyAPIFlagValue == "false" {
disableLegacyAPIs = true
}
_ = disableLegacyAPIs // hush the compiler while we don't have legacy APIs to disable.
// "api/v1={true|false} allows users to enable/disable v1 API.
// This takes preference over api/all and api/legacy, if specified.
disableV1 := disableAllAPIs
v1GroupVersion := "api/v1"
disableV1 = !s.getRuntimeConfigValue(v1GroupVersion, !disableV1)
apiGroupVersionOverrides := map[string]master.APIGroupVersionOverride{}
if disableV1 {
apiGroupVersionOverrides[v1GroupVersion] = master.APIGroupVersionOverride{
Disable: true,
}
}
// "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 = !s.getRuntimeConfigValue(extensionsGroupVersion, !disableExtensions)
if disableExtensions {
apiGroupVersionOverrides[extensionsGroupVersion] = master.APIGroupVersionOverride{
Disable: true,
}
}
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{}
}
apiGroupVersionOverride.ResourceOverrides[resource] = s.getRuntimeConfigValue(key, false)
apiGroupVersionOverrides[extensionsGroupVersion] = apiGroupVersionOverride
}
}
return apiGroupVersionOverrides, nil
}
...@@ -154,3 +154,96 @@ func TestUpdateEtcdOverrides(t *testing.T) { ...@@ -154,3 +154,96 @@ func TestUpdateEtcdOverrides(t *testing.T) {
} }
} }
} }
func TestParseRuntimeConfig(t *testing.T) {
testCases := []struct {
runtimeConfig map[string]string
apiGroupVersionOverrides map[string]master.APIGroupVersionOverride
err bool
}{
{
runtimeConfig: map[string]string{},
apiGroupVersionOverrides: map[string]master.APIGroupVersionOverride{},
err: false,
},
{
// Cannot override v1 resources.
runtimeConfig: map[string]string{
"api/v1/pods": "false",
},
apiGroupVersionOverrides: map[string]master.APIGroupVersionOverride{},
err: true,
},
{
// Disable v1.
runtimeConfig: map[string]string{
"api/v1": "false",
},
apiGroupVersionOverrides: map[string]master.APIGroupVersionOverride{
"api/v1": {
Disable: true,
},
},
err: false,
},
{
// Disable extensions.
runtimeConfig: map[string]string{
"extensions/v1beta1": "false",
},
apiGroupVersionOverrides: map[string]master.APIGroupVersionOverride{
"extensions/v1beta1": {
Disable: true,
},
},
err: false,
},
{
// Disable deployments.
runtimeConfig: map[string]string{
"extensions/v1beta1/deployments": "false",
},
apiGroupVersionOverrides: map[string]master.APIGroupVersionOverride{
"extensions/v1beta1": {
ResourceOverrides: map[string]bool{
"deployments": false,
},
},
},
err: false,
},
{
// Enable deployments and disable jobs.
runtimeConfig: map[string]string{
"extensions/v1beta1/deployments": "true",
"extensions/v1beta1/jobs": "false",
},
apiGroupVersionOverrides: map[string]master.APIGroupVersionOverride{
"extensions/v1beta1": {
ResourceOverrides: map[string]bool{
"deployments": true,
"jobs": false,
},
},
},
err: false,
},
}
for _, test := range testCases {
s := &APIServer{
RuntimeConfig: test.runtimeConfig,
}
apiGroupVersionOverrides, err := s.parseRuntimeConfig()
if err == nil && test.err {
t.Fatalf("expected error for test: %q", test)
} else if err != nil && !test.err {
t.Fatalf("unexpected error: %s, for test: %q", err, test)
}
if err == nil && !reflect.DeepEqual(apiGroupVersionOverrides, test.apiGroupVersionOverrides) {
t.Fatalf("unexpected apiGroupVersionOverrides. Actual: %q, expected: %q", apiGroupVersionOverrides, test.apiGroupVersionOverrides)
}
}
}
...@@ -100,8 +100,7 @@ func TestNew(t *testing.T) { ...@@ -100,8 +100,7 @@ func TestNew(t *testing.T) {
assert.Equal(master.authenticator, config.Authenticator) assert.Equal(master.authenticator, config.Authenticator)
assert.Equal(master.authorizer, config.Authorizer) assert.Equal(master.authorizer, config.Authorizer)
assert.Equal(master.admissionControl, config.AdmissionControl) assert.Equal(master.admissionControl, config.AdmissionControl)
assert.Equal(master.v1, !config.DisableV1) assert.Equal(master.apiGroupVersionOverrides, config.APIGroupVersionOverrides)
assert.Equal(master.exp, config.EnableExp)
assert.Equal(master.requestContextMapper, config.RequestContextMapper) assert.Equal(master.requestContextMapper, config.RequestContextMapper)
assert.Equal(master.cacheTimeout, config.CacheTimeout) assert.Equal(master.cacheTimeout, config.CacheTimeout)
assert.Equal(master.masterCount, config.MasterCount) assert.Equal(master.masterCount, config.MasterCount)
...@@ -366,7 +365,6 @@ func TestGetNodeAddresses(t *testing.T) { ...@@ -366,7 +365,6 @@ func TestGetNodeAddresses(t *testing.T) {
func TestDiscoveryAtAPIS(t *testing.T) { func TestDiscoveryAtAPIS(t *testing.T) {
master, config, assert := setUp(t) master, config, assert := setUp(t)
master.exp = true
// ================= preparation for master.init() ====================== // ================= preparation for master.init() ======================
portRange := util.PortRange{Base: 10, Size: 10} portRange := util.PortRange{Base: 10, Size: 10}
master.serviceNodePortRange = portRange master.serviceNodePortRange = portRange
......
...@@ -144,7 +144,6 @@ func startMasterOrDie(masterConfig *master.Config) (*master.Master, *httptest.Se ...@@ -144,7 +144,6 @@ func startMasterOrDie(masterConfig *master.Config) (*master.Master, *httptest.Se
StorageDestinations: storageDestinations, StorageDestinations: storageDestinations,
StorageVersions: storageVersions, StorageVersions: storageVersions,
KubeletClient: client.FakeKubeletClient{}, KubeletClient: client.FakeKubeletClient{},
EnableExp: true,
EnableLogsSupport: false, EnableLogsSupport: false,
EnableProfiling: true, EnableProfiling: true,
EnableSwaggerSupport: true, EnableSwaggerSupport: true,
...@@ -292,7 +291,6 @@ func RunAMaster(t *testing.T) (*master.Master, *httptest.Server) { ...@@ -292,7 +291,6 @@ func RunAMaster(t *testing.T) (*master.Master, *httptest.Server) {
EnableUISupport: false, EnableUISupport: false,
APIPrefix: "/api", APIPrefix: "/api",
APIGroupPrefix: "/apis", APIGroupPrefix: "/apis",
EnableExp: true,
Authorizer: apiserver.NewAlwaysAllowAuthorizer(), Authorizer: apiserver.NewAlwaysAllowAuthorizer(),
AdmissionControl: admit.NewAlwaysAdmit(), AdmissionControl: admit.NewAlwaysAdmit(),
StorageVersions: storageVersions, StorageVersions: storageVersions,
......
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