refactor resource overrides as positive logic interface
This commit is contained in:
@@ -164,15 +164,6 @@ func (s *StorageDestinations) Backends() []string {
|
||||
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.
|
||||
type APIGroupInfo struct {
|
||||
GroupMeta apimachinery.GroupMeta
|
||||
@@ -218,7 +209,7 @@ type Config struct {
|
||||
// Note that this is ignored if either EnableSwaggerSupport or EnableUISupport is false.
|
||||
EnableSwaggerUI bool
|
||||
// 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
|
||||
EnableIndex bool
|
||||
EnableProfiling bool
|
||||
@@ -305,25 +296,24 @@ type GenericAPIServer struct {
|
||||
cacheTimeout time.Duration
|
||||
MinRequestTimeout time.Duration
|
||||
|
||||
mux apiserver.Mux
|
||||
MuxHelper *apiserver.MuxHelper
|
||||
HandlerContainer *restful.Container
|
||||
RootWebService *restful.WebService
|
||||
enableLogsSupport bool
|
||||
enableUISupport bool
|
||||
enableSwaggerSupport bool
|
||||
enableSwaggerUI bool
|
||||
enableProfiling bool
|
||||
enableWatchCache bool
|
||||
APIPrefix string
|
||||
APIGroupPrefix string
|
||||
corsAllowedOriginList []string
|
||||
authenticator authenticator.Request
|
||||
authorizer authorizer.Authorizer
|
||||
AdmissionControl admission.Interface
|
||||
MasterCount int
|
||||
ApiGroupVersionOverrides map[string]APIGroupVersionOverride
|
||||
RequestContextMapper api.RequestContextMapper
|
||||
mux apiserver.Mux
|
||||
MuxHelper *apiserver.MuxHelper
|
||||
HandlerContainer *restful.Container
|
||||
RootWebService *restful.WebService
|
||||
enableLogsSupport bool
|
||||
enableUISupport bool
|
||||
enableSwaggerSupport bool
|
||||
enableSwaggerUI bool
|
||||
enableProfiling bool
|
||||
enableWatchCache bool
|
||||
APIPrefix string
|
||||
APIGroupPrefix string
|
||||
corsAllowedOriginList []string
|
||||
authenticator authenticator.Request
|
||||
authorizer authorizer.Authorizer
|
||||
AdmissionControl admission.Interface
|
||||
MasterCount int
|
||||
RequestContextMapper api.RequestContextMapper
|
||||
|
||||
// ExternalAddress is the address (hostname or IP and port) that should be used in
|
||||
// external (public internet) URLs for this GenericAPIServer.
|
||||
@@ -451,24 +441,23 @@ func New(c *Config) (*GenericAPIServer, error) {
|
||||
setDefaults(c)
|
||||
|
||||
s := &GenericAPIServer{
|
||||
ServiceClusterIPRange: c.ServiceClusterIPRange,
|
||||
ServiceNodePortRange: c.ServiceNodePortRange,
|
||||
RootWebService: new(restful.WebService),
|
||||
enableLogsSupport: c.EnableLogsSupport,
|
||||
enableUISupport: c.EnableUISupport,
|
||||
enableSwaggerSupport: c.EnableSwaggerSupport,
|
||||
enableSwaggerUI: c.EnableSwaggerUI,
|
||||
enableProfiling: c.EnableProfiling,
|
||||
enableWatchCache: c.EnableWatchCache,
|
||||
APIPrefix: c.APIPrefix,
|
||||
APIGroupPrefix: c.APIGroupPrefix,
|
||||
corsAllowedOriginList: c.CorsAllowedOriginList,
|
||||
authenticator: c.Authenticator,
|
||||
authorizer: c.Authorizer,
|
||||
AdmissionControl: c.AdmissionControl,
|
||||
ApiGroupVersionOverrides: c.APIGroupVersionOverrides,
|
||||
RequestContextMapper: c.RequestContextMapper,
|
||||
Serializer: c.Serializer,
|
||||
ServiceClusterIPRange: c.ServiceClusterIPRange,
|
||||
ServiceNodePortRange: c.ServiceNodePortRange,
|
||||
RootWebService: new(restful.WebService),
|
||||
enableLogsSupport: c.EnableLogsSupport,
|
||||
enableUISupport: c.EnableUISupport,
|
||||
enableSwaggerSupport: c.EnableSwaggerSupport,
|
||||
enableSwaggerUI: c.EnableSwaggerUI,
|
||||
enableProfiling: c.EnableProfiling,
|
||||
enableWatchCache: c.EnableWatchCache,
|
||||
APIPrefix: c.APIPrefix,
|
||||
APIGroupPrefix: c.APIGroupPrefix,
|
||||
corsAllowedOriginList: c.CorsAllowedOriginList,
|
||||
authenticator: c.Authenticator,
|
||||
authorizer: c.Authorizer,
|
||||
AdmissionControl: c.AdmissionControl,
|
||||
RequestContextMapper: c.RequestContextMapper,
|
||||
Serializer: c.Serializer,
|
||||
|
||||
cacheTimeout: c.CacheTimeout,
|
||||
MinRequestTimeout: time.Duration(c.MinRequestTimeout) * time.Second,
|
||||
|
@@ -88,7 +88,6 @@ func TestNew(t *testing.T) {
|
||||
assert.Equal(s.authenticator, config.Authenticator)
|
||||
assert.Equal(s.authorizer, config.Authorizer)
|
||||
assert.Equal(s.AdmissionControl, config.AdmissionControl)
|
||||
assert.Equal(s.ApiGroupVersionOverrides, config.APIGroupVersionOverrides)
|
||||
assert.Equal(s.RequestContextMapper, config.RequestContextMapper)
|
||||
assert.Equal(s.cacheTimeout, config.CacheTimeout)
|
||||
assert.Equal(s.ExternalAddress, config.ExternalHost)
|
||||
|
172
pkg/genericapiserver/resource_config.go
Normal file
172
pkg/genericapiserver/resource_config.go
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
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
|
||||
}
|
99
pkg/genericapiserver/resource_config_test.go
Normal file
99
pkg/genericapiserver/resource_config_test.go
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user