mirror of https://github.com/k3s-io/k3s
Allow enabling/disabling specific extensions/v1beta1 resources
parent
68451f301b
commit
e016e132f5
|
@ -474,8 +474,6 @@ func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig {
|
|||
ret.EnableVersions(
|
||||
admissionregistrationv1beta1.SchemeGroupVersion,
|
||||
apiv1.SchemeGroupVersion,
|
||||
appsv1beta1.SchemeGroupVersion,
|
||||
appsv1beta2.SchemeGroupVersion,
|
||||
appsv1.SchemeGroupVersion,
|
||||
authenticationv1.SchemeGroupVersion,
|
||||
authenticationv1beta1.SchemeGroupVersion,
|
||||
|
@ -499,6 +497,24 @@ func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig {
|
|||
storageapiv1beta1.SchemeGroupVersion,
|
||||
schedulingapiv1beta1.SchemeGroupVersion,
|
||||
)
|
||||
// enable non-deprecated beta resources in extensions/v1beta1 explicitly so we have a full list of what's possible to serve
|
||||
ret.EnableResources(
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"),
|
||||
)
|
||||
// enable deprecated beta resources in extensions/v1beta1 explicitly so we have a full list of what's possible to serve
|
||||
ret.EnableResources(
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("networkpolicies"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("podsecuritypolicies"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicationcontrollers"),
|
||||
)
|
||||
// enable deprecated beta versions explicitly so we have a full list of what's possible to serve
|
||||
ret.EnableVersions(
|
||||
appsv1beta1.SchemeGroupVersion,
|
||||
appsv1beta2.SchemeGroupVersion,
|
||||
)
|
||||
// disable alpha versions explicitly so we have a full list of what's possible to serve
|
||||
ret.DisableVersions(
|
||||
auditregistrationv1alpha1.SchemeGroupVersion,
|
||||
|
|
|
@ -52,39 +52,53 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag
|
|||
|
||||
// This is a dummy replication controller for scale subresource purposes.
|
||||
// TODO: figure out how to enable this only if needed as a part of scale subresource GA.
|
||||
controllerStorage := expcontrollerstore.NewStorage(restOptionsGetter)
|
||||
storage["replicationcontrollers"] = controllerStorage.ReplicationController
|
||||
storage["replicationcontrollers/scale"] = controllerStorage.Scale
|
||||
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicationcontrollers")) {
|
||||
controllerStorage := expcontrollerstore.NewStorage(restOptionsGetter)
|
||||
storage["replicationcontrollers"] = controllerStorage.ReplicationController
|
||||
storage["replicationcontrollers/scale"] = controllerStorage.Scale
|
||||
}
|
||||
|
||||
// daemonsets
|
||||
daemonSetStorage, daemonSetStatusStorage := daemonstore.NewREST(restOptionsGetter)
|
||||
storage["daemonsets"] = daemonSetStorage.WithCategories(nil)
|
||||
storage["daemonsets/status"] = daemonSetStatusStorage
|
||||
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets")) {
|
||||
daemonSetStorage, daemonSetStatusStorage := daemonstore.NewREST(restOptionsGetter)
|
||||
storage["daemonsets"] = daemonSetStorage.WithCategories(nil)
|
||||
storage["daemonsets/status"] = daemonSetStatusStorage
|
||||
}
|
||||
|
||||
//deployments
|
||||
deploymentStorage := deploymentstore.NewStorage(restOptionsGetter)
|
||||
storage["deployments"] = deploymentStorage.Deployment.WithCategories(nil)
|
||||
storage["deployments/status"] = deploymentStorage.Status
|
||||
storage["deployments/rollback"] = deploymentStorage.Rollback
|
||||
storage["deployments/scale"] = deploymentStorage.Scale
|
||||
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments")) {
|
||||
deploymentStorage := deploymentstore.NewStorage(restOptionsGetter)
|
||||
storage["deployments"] = deploymentStorage.Deployment.WithCategories(nil)
|
||||
storage["deployments/status"] = deploymentStorage.Status
|
||||
storage["deployments/rollback"] = deploymentStorage.Rollback
|
||||
storage["deployments/scale"] = deploymentStorage.Scale
|
||||
}
|
||||
// ingresses
|
||||
ingressStorage, ingressStatusStorage := ingressstore.NewREST(restOptionsGetter)
|
||||
storage["ingresses"] = ingressStorage
|
||||
storage["ingresses/status"] = ingressStatusStorage
|
||||
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses")) {
|
||||
ingressStorage, ingressStatusStorage := ingressstore.NewREST(restOptionsGetter)
|
||||
storage["ingresses"] = ingressStorage
|
||||
storage["ingresses/status"] = ingressStatusStorage
|
||||
}
|
||||
|
||||
// podsecuritypolicy
|
||||
podSecurityPolicyStorage := pspstore.NewREST(restOptionsGetter)
|
||||
storage["podSecurityPolicies"] = podSecurityPolicyStorage
|
||||
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("podsecuritypolicies")) {
|
||||
podSecurityPolicyStorage := pspstore.NewREST(restOptionsGetter)
|
||||
storage["podSecurityPolicies"] = podSecurityPolicyStorage
|
||||
}
|
||||
|
||||
// replicasets
|
||||
replicaSetStorage := replicasetstore.NewStorage(restOptionsGetter)
|
||||
storage["replicasets"] = replicaSetStorage.ReplicaSet.WithCategories(nil)
|
||||
storage["replicasets/status"] = replicaSetStorage.Status
|
||||
storage["replicasets/scale"] = replicaSetStorage.Scale
|
||||
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets")) {
|
||||
replicaSetStorage := replicasetstore.NewStorage(restOptionsGetter)
|
||||
storage["replicasets"] = replicaSetStorage.ReplicaSet.WithCategories(nil)
|
||||
storage["replicasets/status"] = replicaSetStorage.Status
|
||||
storage["replicasets/scale"] = replicaSetStorage.Scale
|
||||
}
|
||||
|
||||
// networkpolicies
|
||||
networkExtensionsStorage := networkpolicystore.NewREST(restOptionsGetter)
|
||||
storage["networkpolicies"] = networkExtensionsStorage
|
||||
if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("networkpolicies")) {
|
||||
networkExtensionsStorage := networkpolicystore.NewREST(restOptionsGetter)
|
||||
storage["networkpolicies"] = networkExtensionsStorage
|
||||
}
|
||||
|
||||
return storage
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ func MergeAPIResourceConfigs(
|
|||
}
|
||||
|
||||
tokens := strings.Split(key, "/")
|
||||
if len(tokens) != 2 {
|
||||
if len(tokens) < 2 {
|
||||
continue
|
||||
}
|
||||
groupVersionString := tokens[0] + "/" + tokens[1]
|
||||
|
@ -103,6 +103,12 @@ func MergeAPIResourceConfigs(
|
|||
return nil, fmt.Errorf("invalid key %s", key)
|
||||
}
|
||||
|
||||
// individual resource enablement/disablement is only supported in the extensions/v1beta1 API group for legacy reasons.
|
||||
// all other API groups are expected to contain coherent sets of resources that are enabled/disabled together.
|
||||
if len(tokens) > 2 && (groupVersion != schema.GroupVersion{Group: "extensions", Version: "v1beta1"}) {
|
||||
return nil, fmt.Errorf("invalid key %s, individual resource enablement/disablement is not supported in %s", key, groupVersion.String())
|
||||
}
|
||||
|
||||
// Exclude group not registered into the registry.
|
||||
if !registry.IsGroupRegistered(groupVersion.Group) {
|
||||
continue
|
||||
|
@ -117,10 +123,22 @@ func MergeAPIResourceConfigs(
|
|||
return nil, err
|
||||
}
|
||||
if enabled {
|
||||
// enable the groupVersion for "group/version=true" and "group/version/resource=true"
|
||||
resourceConfig.EnableVersions(groupVersion)
|
||||
} else {
|
||||
} else if len(tokens) == 2 {
|
||||
// disable the groupVersion only for "group/version=false", not "group/version/resource=false"
|
||||
resourceConfig.DisableVersions(groupVersion)
|
||||
}
|
||||
|
||||
if len(tokens) < 3 {
|
||||
continue
|
||||
}
|
||||
groupVersionResource := groupVersion.WithResource(tokens[2])
|
||||
if enabled {
|
||||
resourceConfig.EnableResources(groupVersionResource)
|
||||
} else {
|
||||
resourceConfig.DisableResources(groupVersionResource)
|
||||
}
|
||||
}
|
||||
|
||||
return resourceConfig, nil
|
||||
|
|
|
@ -117,6 +117,11 @@ func TestParseRuntimeConfig(t *testing.T) {
|
|||
expectedAPIConfig: func() *serverstore.ResourceConfig {
|
||||
config := newFakeAPIResourceConfigSource()
|
||||
config.EnableVersions(scheme.PrioritizedVersionsAllGroups()...)
|
||||
config.EnableResources(
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"),
|
||||
)
|
||||
return config
|
||||
},
|
||||
err: false,
|
||||
|
@ -133,10 +138,71 @@ func TestParseRuntimeConfig(t *testing.T) {
|
|||
expectedAPIConfig: func() *serverstore.ResourceConfig {
|
||||
config := newFakeAPIResourceConfigSource()
|
||||
config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion)
|
||||
config.DisableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"))
|
||||
return config
|
||||
},
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
// enable specific extensions resources
|
||||
runtimeConfig: map[string]string{
|
||||
"extensions/v1beta1/deployments": "true",
|
||||
},
|
||||
defaultResourceConfig: func() *serverstore.ResourceConfig {
|
||||
return newFakeAPIResourceConfigSource()
|
||||
},
|
||||
expectedAPIConfig: func() *serverstore.ResourceConfig {
|
||||
config := newFakeAPIResourceConfigSource()
|
||||
config.EnableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"))
|
||||
return config
|
||||
},
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
// disable specific extensions resources
|
||||
runtimeConfig: map[string]string{
|
||||
"extensions/v1beta1/ingresses": "false",
|
||||
},
|
||||
defaultResourceConfig: func() *serverstore.ResourceConfig {
|
||||
return newFakeAPIResourceConfigSource()
|
||||
},
|
||||
expectedAPIConfig: func() *serverstore.ResourceConfig {
|
||||
config := newFakeAPIResourceConfigSource()
|
||||
config.DisableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"))
|
||||
return config
|
||||
},
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
// disable all extensions resources
|
||||
runtimeConfig: map[string]string{
|
||||
"extensions/v1beta1": "false",
|
||||
},
|
||||
defaultResourceConfig: func() *serverstore.ResourceConfig {
|
||||
return newFakeAPIResourceConfigSource()
|
||||
},
|
||||
expectedAPIConfig: func() *serverstore.ResourceConfig {
|
||||
config := newFakeAPIResourceConfigSource()
|
||||
config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion)
|
||||
return config
|
||||
},
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
// disable a non-extensions resource
|
||||
runtimeConfig: map[string]string{
|
||||
"apps/v1/deployments": "false",
|
||||
},
|
||||
defaultResourceConfig: func() *serverstore.ResourceConfig {
|
||||
return newFakeAPIResourceConfigSource()
|
||||
},
|
||||
expectedAPIConfig: func() *serverstore.ResourceConfig {
|
||||
config := newFakeAPIResourceConfigSource()
|
||||
config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion)
|
||||
return config
|
||||
},
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
for index, test := range testCases {
|
||||
t.Log(scheme.PrioritizedVersionsAllGroups())
|
||||
|
@ -161,6 +227,14 @@ func newFakeAPIResourceConfigSource() *serverstore.ResourceConfig {
|
|||
apiv1.SchemeGroupVersion,
|
||||
extensionsapiv1beta1.SchemeGroupVersion,
|
||||
)
|
||||
ret.EnableResources(
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"),
|
||||
)
|
||||
ret.DisableResources(
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"),
|
||||
)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
// APIResourceConfigSource is the interface to determine which groups and versions are enabled
|
||||
type APIResourceConfigSource interface {
|
||||
VersionEnabled(version schema.GroupVersion) bool
|
||||
ResourceEnabled(resource schema.GroupVersionResource) bool
|
||||
AnyVersionForGroupEnabled(group string) bool
|
||||
}
|
||||
|
||||
|
@ -30,22 +31,29 @@ var _ APIResourceConfigSource = &ResourceConfig{}
|
|||
|
||||
type ResourceConfig struct {
|
||||
GroupVersionConfigs map[schema.GroupVersion]bool
|
||||
ResourceConfigs map[schema.GroupVersionResource]bool
|
||||
}
|
||||
|
||||
func NewResourceConfig() *ResourceConfig {
|
||||
return &ResourceConfig{GroupVersionConfigs: map[schema.GroupVersion]bool{}}
|
||||
return &ResourceConfig{GroupVersionConfigs: map[schema.GroupVersion]bool{}, ResourceConfigs: map[schema.GroupVersionResource]bool{}}
|
||||
}
|
||||
|
||||
func (o *ResourceConfig) DisableAll() {
|
||||
for k := range o.GroupVersionConfigs {
|
||||
o.GroupVersionConfigs[k] = false
|
||||
}
|
||||
for k := range o.ResourceConfigs {
|
||||
o.ResourceConfigs[k] = false
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ResourceConfig) EnableAll() {
|
||||
for k := range o.GroupVersionConfigs {
|
||||
o.GroupVersionConfigs[k] = true
|
||||
}
|
||||
for k := range o.ResourceConfigs {
|
||||
o.ResourceConfigs[k] = true
|
||||
}
|
||||
}
|
||||
|
||||
// DisableVersions disables the versions entirely.
|
||||
|
@ -70,6 +78,29 @@ func (o *ResourceConfig) VersionEnabled(version schema.GroupVersion) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (o *ResourceConfig) DisableResources(resources ...schema.GroupVersionResource) {
|
||||
for _, resource := range resources {
|
||||
o.ResourceConfigs[resource] = false
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ResourceConfig) EnableResources(resources ...schema.GroupVersionResource) {
|
||||
for _, resource := range resources {
|
||||
o.ResourceConfigs[resource] = true
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ResourceConfig) ResourceEnabled(resource schema.GroupVersionResource) bool {
|
||||
if !o.VersionEnabled(resource.GroupVersion()) {
|
||||
return false
|
||||
}
|
||||
resourceEnabled, explicitlySet := o.ResourceConfigs[resource]
|
||||
if !explicitlySet {
|
||||
return true
|
||||
}
|
||||
return resourceEnabled
|
||||
}
|
||||
|
||||
func (o *ResourceConfig) AnyVersionForGroupEnabled(group string) bool {
|
||||
for version := range o.GroupVersionConfigs {
|
||||
if version.Group == group {
|
||||
|
|
|
@ -43,6 +43,84 @@ func TestDisabledVersion(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDisabledResource(t *testing.T) {
|
||||
g1v1 := schema.GroupVersion{Group: "group1", Version: "version1"}
|
||||
g1v1rUnspecified := g1v1.WithResource("unspecified")
|
||||
g1v1rEnabled := g1v1.WithResource("enabled")
|
||||
g1v1rDisabled := g1v1.WithResource("disabled")
|
||||
g1v2 := schema.GroupVersion{Group: "group1", Version: "version2"}
|
||||
g1v2rUnspecified := g1v2.WithResource("unspecified")
|
||||
g1v2rEnabled := g1v2.WithResource("enabled")
|
||||
g1v2rDisabled := g1v2.WithResource("disabled")
|
||||
g2v1 := schema.GroupVersion{Group: "group2", Version: "version1"}
|
||||
g2v1rUnspecified := g2v1.WithResource("unspecified")
|
||||
g2v1rEnabled := g2v1.WithResource("enabled")
|
||||
g2v1rDisabled := g2v1.WithResource("disabled")
|
||||
|
||||
config := NewResourceConfig()
|
||||
|
||||
config.DisableVersions(g1v1)
|
||||
config.EnableVersions(g1v2, g2v1)
|
||||
|
||||
config.EnableResources(g1v1rEnabled, g1v2rEnabled, g2v1rEnabled)
|
||||
config.DisableResources(g1v1rDisabled, g1v2rDisabled, g2v1rDisabled)
|
||||
|
||||
// all resources under g1v1 are disabled because the group-version is disabled
|
||||
if config.ResourceEnabled(g1v1rUnspecified) {
|
||||
t.Errorf("expected disabled for %v, from %v", g1v1rUnspecified, config)
|
||||
}
|
||||
if config.ResourceEnabled(g1v1rEnabled) {
|
||||
t.Errorf("expected disabled for %v, from %v", g1v1rEnabled, config)
|
||||
}
|
||||
if config.ResourceEnabled(g1v1rDisabled) {
|
||||
t.Errorf("expected disabled for %v, from %v", g1v1rDisabled, config)
|
||||
}
|
||||
|
||||
// explicitly disabled resources in enabled group-versions are disabled
|
||||
if config.ResourceEnabled(g1v2rDisabled) {
|
||||
t.Errorf("expected disabled for %v, from %v", g1v2rDisabled, config)
|
||||
}
|
||||
if config.ResourceEnabled(g2v1rDisabled) {
|
||||
t.Errorf("expected disabled for %v, from %v", g2v1rDisabled, config)
|
||||
}
|
||||
|
||||
// unspecified and explicitly enabled resources in enabled group-versions are enabled
|
||||
if !config.ResourceEnabled(g1v2rUnspecified) {
|
||||
t.Errorf("expected enabled for %v, from %v", g1v2rUnspecified, config)
|
||||
}
|
||||
if !config.ResourceEnabled(g1v2rEnabled) {
|
||||
t.Errorf("expected enabled for %v, from %v", g1v2rEnabled, config)
|
||||
}
|
||||
if !config.ResourceEnabled(g2v1rUnspecified) {
|
||||
t.Errorf("expected enabled for %v, from %v", g2v1rUnspecified, config)
|
||||
}
|
||||
if !config.ResourceEnabled(g2v1rEnabled) {
|
||||
t.Errorf("expected enabled for %v, from %v", g2v1rEnabled, config)
|
||||
}
|
||||
|
||||
// Enable all enables specific resources
|
||||
config.EnableAll()
|
||||
|
||||
// all resources under g1v1 are now enabled
|
||||
if !config.ResourceEnabled(g1v1rUnspecified) {
|
||||
t.Errorf("expected enabled for %v, from %v", g1v1rUnspecified, config)
|
||||
}
|
||||
if !config.ResourceEnabled(g1v1rEnabled) {
|
||||
t.Errorf("expected enabled for %v, from %v", g1v1rEnabled, config)
|
||||
}
|
||||
if !config.ResourceEnabled(g1v1rDisabled) {
|
||||
t.Errorf("expected enabled for %v, from %v", g1v1rDisabled, config)
|
||||
}
|
||||
|
||||
// previously disabled resources are now enabled
|
||||
if !config.ResourceEnabled(g1v2rDisabled) {
|
||||
t.Errorf("expected enabled for %v, from %v", g1v2rDisabled, config)
|
||||
}
|
||||
if !config.ResourceEnabled(g2v1rDisabled) {
|
||||
t.Errorf("expected enabled for %v, from %v", g2v1rDisabled, config)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnyVersionForGroupEnabled(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
Loading…
Reference in New Issue