Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
7bcc4a67
Commit
7bcc4a67
authored
Oct 12, 2015
by
nikhiljindal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allowing runtimeConfig to support enabling/disabling specific extension resources
parent
5174ca21
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
230 additions
and
68 deletions
+230
-68
server.go
cmd/kube-apiserver/app/server.go
+65
-27
server_test.go
cmd/kube-apiserver/app/server_test.go
+93
-0
master.go
pkg/master/master.go
+71
-36
master_test.go
pkg/master/master_test.go
+1
-3
master_utils.go
test/integration/framework/master_utils.go
+0
-2
No files found.
cmd/kube-apiserver/app/server.go
View file @
7bcc4a67
...
...
@@ -408,29 +408,10 @@ func (s *APIServer) Run(_ []string) error {
glog
.
Fatalf
(
"Failure to start kubelet client: %v"
,
err
)
}
// "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
apiGroupVersionOverrides
,
err
:=
s
.
parseRuntimeConfig
()
if
err
!=
nil
{
glog
.
Fatalf
(
"error in parsing runtime-config: %s"
,
err
)
}
_
=
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
{
Host
:
net
.
JoinHostPort
(
s
.
InsecureBindAddress
.
String
(),
strconv
.
Itoa
(
s
.
InsecurePort
)),
...
...
@@ -458,17 +439,17 @@ func (s *APIServer) Run(_ []string) error {
}
storageDestinations
.
AddAPIGroup
(
""
,
etcdStorage
)
if
enableExp
{
if
!
apiGroupVersionOverrides
[
"extensions/v1beta1"
]
.
Disable
{
expGroup
,
err
:=
latest
.
Group
(
"extensions"
)
if
err
!=
nil
{
glog
.
Fatalf
(
"Ex
perimental
API is enabled in runtime config, but not enabled in the environment variable KUBE_API_VERSIONS. Error: %v"
,
err
)
glog
.
Fatalf
(
"Ex
tensions
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
{
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
)
if
err
!=
nil
{
glog
.
Fatalf
(
"Invalid ex
perimental
storage version or misconfigured etcd: %v"
,
err
)
glog
.
Fatalf
(
"Invalid ex
tensions
storage version or misconfigured etcd: %v"
,
err
)
}
storageDestinations
.
AddAPIGroup
(
"extensions"
,
expEtcdStorage
)
}
...
...
@@ -558,8 +539,7 @@ func (s *APIServer) Run(_ []string) error {
SupportsBasicAuth
:
len
(
s
.
BasicAuthFile
)
>
0
,
Authorizer
:
authorizer
,
AdmissionControl
:
admissionController
,
DisableV1
:
disableV1
,
EnableExp
:
enableExp
,
APIGroupVersionOverrides
:
apiGroupVersionOverrides
,
MasterServiceNamespace
:
s
.
MasterServiceNamespace
,
ClusterName
:
s
.
ClusterName
,
ExternalHost
:
s
.
ExternalHost
,
...
...
@@ -680,3 +660,61 @@ func (s *APIServer) getRuntimeConfigValue(apiKey string, defaultValue bool) bool
}
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
}
cmd/kube-apiserver/app/server_test.go
View file @
7bcc4a67
...
...
@@ -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
)
}
}
}
pkg/master/master.go
View file @
7bcc4a67
...
...
@@ -80,6 +80,7 @@ import (
"k8s.io/kubernetes/pkg/ui"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/sets"
utilSets
"k8s.io/kubernetes/pkg/util/sets"
daemonetcd
"k8s.io/kubernetes/pkg/registry/daemonset/etcd"
horizontalpodautoscaleretcd
"k8s.io/kubernetes/pkg/registry/horizontalpodautoscaler/etcd"
...
...
@@ -166,6 +167,15 @@ 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
}
// Config is a structure used to configure a Master.
type
Config
struct
{
StorageDestinations
StorageDestinations
...
...
@@ -180,9 +190,8 @@ type Config struct {
EnableUISupport
bool
// allow downstream consumers to disable swagger
EnableSwaggerSupport
bool
// allow api versions to be conditionally disabled
DisableV1
bool
EnableExp
bool
// Allows api group versions or specific resources to be conditionally enabled/disabled.
APIGroupVersionOverrides
map
[
string
]
APIGroupVersionOverride
// allow downstream consumers to disable the index route
EnableIndex
bool
EnableProfiling
bool
...
...
@@ -288,8 +297,7 @@ type Master struct {
authorizer
authorizer
.
Authorizer
admissionControl
admission
.
Interface
masterCount
int
v1
bool
exp
bool
apiGroupVersionOverrides
map
[
string
]
APIGroupVersionOverride
requestContextMapper
api
.
RequestContextMapper
// External host is the name that should be used in external (public internet) URLs for this master
...
...
@@ -450,8 +458,7 @@ func New(c *Config) *Master {
authenticator
:
c
.
Authenticator
,
authorizer
:
c
.
Authorizer
,
admissionControl
:
c
.
AdmissionControl
,
v1
:
!
c
.
DisableV1
,
exp
:
c
.
EnableExp
,
apiGroupVersionOverrides
:
c
.
APIGroupVersionOverrides
,
requestContextMapper
:
c
.
RequestContextMapper
,
cacheTimeout
:
c
.
CacheTimeout
,
...
...
@@ -624,7 +631,8 @@ func (m *Master) init(c *Config) {
}
apiVersions
:=
[]
string
{}
if
m
.
v1
{
// Install v1 unless disabled.
if
!
m
.
apiGroupVersionOverrides
[
"api/v1"
]
.
Disable
{
if
err
:=
m
.
api_v1
()
.
InstallREST
(
m
.
handlerContainer
);
err
!=
nil
{
glog
.
Fatalf
(
"Unable to setup API v1: %v"
,
err
)
}
...
...
@@ -637,7 +645,8 @@ func (m *Master) init(c *Config) {
// allGroups records all supported groups at /apis
allGroups
:=
[]
unversioned
.
APIGroup
{}
if
m
.
exp
{
// Install extensions unless disabled.
if
!
m
.
apiGroupVersionOverrides
[
"extensions/v1beta1"
]
.
Disable
{
m
.
thirdPartyStorage
=
c
.
StorageDestinations
.
APIGroups
[
"extensions"
]
.
Default
m
.
thirdPartyResources
=
map
[
string
]
*
thirdpartyresourcedataetcd
.
REST
{}
...
...
@@ -1023,17 +1032,34 @@ func (m *Master) thirdpartyapi(group, kind, version string) *apiserver.APIGroupV
// experimental returns the resources and codec for the experimental api
func
(
m
*
Master
)
experimental
(
c
*
Config
)
*
apiserver
.
APIGroupVersion
{
controllerStorage
:=
expcontrolleretcd
.
NewStorage
(
c
.
StorageDestinations
.
get
(
""
,
"replicationControllers"
))
// All resources except these are disabled by default.
enabledResources
:=
utilSets
.
NewString
(
"jobs"
,
"horizontalpodautoscalers"
,
"ingress"
)
resourceOverrides
:=
m
.
apiGroupVersionOverrides
[
"extensions/v1beta1"
]
.
ResourceOverrides
isEnabled
:=
func
(
resource
string
)
bool
{
// Check if the resource has been overriden.
enabled
,
ok
:=
resourceOverrides
[
resource
]
if
!
ok
{
return
enabledResources
.
Has
(
resource
)
}
return
enabled
}
dbClient
:=
func
(
resource
string
)
storage
.
Interface
{
return
c
.
StorageDestinations
.
get
(
"extensions"
,
resource
)
}
storage
:=
map
[
string
]
rest
.
Storage
{}
if
isEnabled
(
"replicationcontrollers"
)
{
controllerStorage
:=
expcontrolleretcd
.
NewStorage
(
c
.
StorageDestinations
.
get
(
""
,
"replicationControllers"
))
storage
[
"replicationcontrollers"
]
=
controllerStorage
.
ReplicationController
storage
[
"replicationcontrollers/scale"
]
=
controllerStorage
.
Scale
}
if
isEnabled
(
"horizontalpodautoscalers"
)
{
autoscalerStorage
,
autoscalerStatusStorage
:=
horizontalpodautoscaleretcd
.
NewREST
(
dbClient
(
"horizonalpodautoscalers"
))
storage
[
"horizontalpodautoscalers"
]
=
autoscalerStorage
storage
[
"horizontalpodautoscalers/status"
]
=
autoscalerStatusStorage
}
if
isEnabled
(
"thirdpartyresources"
)
{
thirdPartyResourceStorage
:=
thirdpartyresourceetcd
.
NewREST
(
dbClient
(
"thirdpartyresources"
))
daemonSetStorage
,
daemonSetStatusStorage
:=
daemonetcd
.
NewREST
(
dbClient
(
"daemonsets"
))
deploymentStorage
:=
deploymentetcd
.
NewStorage
(
dbClient
(
"deployments"
))
jobStorage
,
jobStatusStorage
:=
jobetcd
.
NewREST
(
dbClient
(
"jobs"
))
ingressStorage
,
ingressStatusStorage
:=
ingressetcd
.
NewREST
(
dbClient
(
"ingress"
))
thirdPartyControl
:=
ThirdPartyController
{
master
:
m
,
thirdPartyResourceRegistry
:
thirdPartyResourceStorage
,
...
...
@@ -1045,23 +1071,32 @@ func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion {
}
},
10
*
time
.
Second
)
}()
storage
:=
map
[
string
]
rest
.
Storage
{
strings
.
ToLower
(
"replicationControllers"
)
:
controllerStorage
.
ReplicationController
,
strings
.
ToLower
(
"replicationControllers/scale"
)
:
controllerStorage
.
Scale
,
strings
.
ToLower
(
"horizontalpodautoscalers"
)
:
autoscalerStorage
,
strings
.
ToLower
(
"horizontalpodautoscalers/status"
)
:
autoscalerStatusStorage
,
strings
.
ToLower
(
"thirdpartyresources"
)
:
thirdPartyResourceStorage
,
strings
.
ToLower
(
"daemonsets"
)
:
daemonSetStorage
,
strings
.
ToLower
(
"daemonsets/status"
)
:
daemonSetStatusStorage
,
strings
.
ToLower
(
"deployments"
)
:
deploymentStorage
.
Deployment
,
strings
.
ToLower
(
"deployments/scale"
)
:
deploymentStorage
.
Scale
,
strings
.
ToLower
(
"jobs"
)
:
jobStorage
,
strings
.
ToLower
(
"jobs/status"
)
:
jobStatusStorage
,
strings
.
ToLower
(
"ingress"
)
:
ingressStorage
,
strings
.
ToLower
(
"ingress/status"
)
:
ingressStatusStorage
,
}
expMeta
:=
latest
.
GroupOrDie
(
"extensions"
)
storage
[
"thirdpartyresources"
]
=
thirdPartyResourceStorage
}
if
isEnabled
(
"daemonsets"
)
{
daemonSetStorage
,
daemonSetStatusStorage
:=
daemonetcd
.
NewREST
(
dbClient
(
"daemonsets"
))
storage
[
"daemonsets"
]
=
daemonSetStorage
storage
[
"daemonsets/status"
]
=
daemonSetStatusStorage
}
if
isEnabled
(
"deployments"
)
{
deploymentStorage
:=
deploymentetcd
.
NewStorage
(
dbClient
(
"deployments"
))
storage
[
"deployments"
]
=
deploymentStorage
.
Deployment
storage
[
"deployments/scale"
]
=
deploymentStorage
.
Scale
}
if
isEnabled
(
"jobs"
)
{
jobStorage
,
jobStatusStorage
:=
jobetcd
.
NewREST
(
dbClient
(
"jobs"
))
storage
[
"jobs"
]
=
jobStorage
storage
[
"jobs/status"
]
=
jobStatusStorage
}
if
isEnabled
(
"ingress"
)
{
ingressStorage
,
ingressStatusStorage
:=
ingressetcd
.
NewREST
(
dbClient
(
"ingress"
))
storage
[
"ingress"
]
=
ingressStorage
storage
[
"ingress/status"
]
=
ingressStatusStorage
}
extensionsGroup
:=
latest
.
GroupOrDie
(
"extensions"
)
return
&
apiserver
.
APIGroupVersion
{
Root
:
m
.
apiGroupPrefix
,
...
...
@@ -1071,11 +1106,11 @@ func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion {
Convertor
:
api
.
Scheme
,
Typer
:
api
.
Scheme
,
Mapper
:
ex
pMeta
.
RESTMapper
,
Codec
:
ex
pMeta
.
Codec
,
Linker
:
ex
pMeta
.
SelfLinker
,
Mapper
:
ex
tensionsGroup
.
RESTMapper
,
Codec
:
ex
tensionsGroup
.
Codec
,
Linker
:
ex
tensionsGroup
.
SelfLinker
,
Storage
:
storage
,
Version
:
ex
pMeta
.
GroupVersion
,
Version
:
ex
tensionsGroup
.
GroupVersion
,
ServerVersion
:
latest
.
GroupOrDie
(
""
)
.
GroupVersion
,
Admit
:
m
.
admissionControl
,
...
...
pkg/master/master_test.go
View file @
7bcc4a67
...
...
@@ -100,8 +100,7 @@ func TestNew(t *testing.T) {
assert
.
Equal
(
master
.
authenticator
,
config
.
Authenticator
)
assert
.
Equal
(
master
.
authorizer
,
config
.
Authorizer
)
assert
.
Equal
(
master
.
admissionControl
,
config
.
AdmissionControl
)
assert
.
Equal
(
master
.
v1
,
!
config
.
DisableV1
)
assert
.
Equal
(
master
.
exp
,
config
.
EnableExp
)
assert
.
Equal
(
master
.
apiGroupVersionOverrides
,
config
.
APIGroupVersionOverrides
)
assert
.
Equal
(
master
.
requestContextMapper
,
config
.
RequestContextMapper
)
assert
.
Equal
(
master
.
cacheTimeout
,
config
.
CacheTimeout
)
assert
.
Equal
(
master
.
masterCount
,
config
.
MasterCount
)
...
...
@@ -366,7 +365,6 @@ func TestGetNodeAddresses(t *testing.T) {
func
TestDiscoveryAtAPIS
(
t
*
testing
.
T
)
{
master
,
config
,
assert
:=
setUp
(
t
)
master
.
exp
=
true
// ================= preparation for master.init() ======================
portRange
:=
util
.
PortRange
{
Base
:
10
,
Size
:
10
}
master
.
serviceNodePortRange
=
portRange
...
...
test/integration/framework/master_utils.go
View file @
7bcc4a67
...
...
@@ -144,7 +144,6 @@ func startMasterOrDie(masterConfig *master.Config) (*master.Master, *httptest.Se
StorageDestinations
:
storageDestinations
,
StorageVersions
:
storageVersions
,
KubeletClient
:
client
.
FakeKubeletClient
{},
EnableExp
:
true
,
EnableLogsSupport
:
false
,
EnableProfiling
:
true
,
EnableSwaggerSupport
:
true
,
...
...
@@ -292,7 +291,6 @@ func RunAMaster(t *testing.T) (*master.Master, *httptest.Server) {
EnableUISupport
:
false
,
APIPrefix
:
"/api"
,
APIGroupPrefix
:
"/apis"
,
EnableExp
:
true
,
Authorizer
:
apiserver
.
NewAlwaysAllowAuthorizer
(),
AdmissionControl
:
admit
.
NewAlwaysAdmit
(),
StorageVersions
:
storageVersions
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment