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
fc0a3c6d
Commit
fc0a3c6d
authored
Jun 08, 2016
by
Dominika Hodovska
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow shareable resources for admission control plugins
parent
976ca09d
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
216 additions
and
89 deletions
+216
-89
server.go
cmd/kube-apiserver/app/server.go
+7
-0
server.go
federation/cmd/federation-apiserver/app/server.go
+6
-1
init.go
pkg/admission/init.go
+71
-0
types.go
pkg/admission/types.go
+30
-0
factory.go
pkg/controller/framework/informers/factory.go
+18
-0
admission.go
plugin/pkg/admission/namespace/autoprovision/admission.go
+18
-26
admission_test.go
...n/pkg/admission/namespace/autoprovision/admission_test.go
+25
-11
admission.go
plugin/pkg/admission/namespace/exists/admission.go
+18
-23
admission.go
plugin/pkg/admission/namespace/lifecycle/admission.go
+16
-23
admission_test.go
plugin/pkg/admission/namespace/lifecycle/admission_test.go
+7
-5
No files found.
cmd/kube-apiserver/app/server.go
View file @
fc0a3c6d
...
@@ -25,6 +25,7 @@ import (
...
@@ -25,6 +25,7 @@ import (
"net/url"
"net/url"
"strconv"
"strconv"
"strings"
"strings"
"time"
"github.com/golang/glog"
"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/spf13/cobra"
...
@@ -41,6 +42,7 @@ import (
...
@@ -41,6 +42,7 @@ import (
"k8s.io/kubernetes/pkg/apiserver/authenticator"
"k8s.io/kubernetes/pkg/apiserver/authenticator"
"k8s.io/kubernetes/pkg/capabilities"
"k8s.io/kubernetes/pkg/capabilities"
"k8s.io/kubernetes/pkg/cloudprovider"
"k8s.io/kubernetes/pkg/cloudprovider"
"k8s.io/kubernetes/pkg/controller/framework/informers"
serviceaccountcontroller
"k8s.io/kubernetes/pkg/controller/serviceaccount"
serviceaccountcontroller
"k8s.io/kubernetes/pkg/controller/serviceaccount"
"k8s.io/kubernetes/pkg/genericapiserver"
"k8s.io/kubernetes/pkg/genericapiserver"
kubeletclient
"k8s.io/kubernetes/pkg/kubelet/client"
kubeletclient
"k8s.io/kubernetes/pkg/kubelet/client"
...
@@ -243,6 +245,11 @@ func Run(s *options.APIServer) error {
...
@@ -243,6 +245,11 @@ func Run(s *options.APIServer) error {
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
Errorf
(
"Failed to create clientset: %v"
,
err
)
glog
.
Errorf
(
"Failed to create clientset: %v"
,
err
)
}
}
namespaceInformer
:=
informers
.
CreateSharedNamespaceIndexInformer
(
client
,
5
*
time
.
Minute
)
pluginInit
:=
admission
.
NewPluginInitializer
()
pluginInit
.
SetNamespaceInformer
(
namespaceInformer
)
admissionController
:=
admission
.
NewFromPlugins
(
client
,
admissionControlPluginNames
,
s
.
AdmissionControlConfigFile
)
admissionController
:=
admission
.
NewFromPlugins
(
client
,
admissionControlPluginNames
,
s
.
AdmissionControlConfigFile
)
genericConfig
:=
genericapiserver
.
NewConfig
(
s
.
ServerRunOptions
)
genericConfig
:=
genericapiserver
.
NewConfig
(
s
.
ServerRunOptions
)
...
...
federation/cmd/federation-apiserver/app/server.go
View file @
fc0a3c6d
...
@@ -21,6 +21,7 @@ package app
...
@@ -21,6 +21,7 @@ package app
import
(
import
(
"strings"
"strings"
"time"
"github.com/golang/glog"
"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/spf13/cobra"
...
@@ -31,6 +32,7 @@ import (
...
@@ -31,6 +32,7 @@ import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apiserver"
"k8s.io/kubernetes/pkg/apiserver"
"k8s.io/kubernetes/pkg/apiserver/authenticator"
"k8s.io/kubernetes/pkg/apiserver/authenticator"
"k8s.io/kubernetes/pkg/controller/framework/informers"
"k8s.io/kubernetes/pkg/genericapiserver"
"k8s.io/kubernetes/pkg/genericapiserver"
genericoptions
"k8s.io/kubernetes/pkg/genericapiserver/options"
genericoptions
"k8s.io/kubernetes/pkg/genericapiserver/options"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/cachesize"
...
@@ -119,8 +121,11 @@ func Run(s *genericoptions.ServerRunOptions) error {
...
@@ -119,8 +121,11 @@ func Run(s *genericoptions.ServerRunOptions) error {
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
Errorf
(
"Failed to create clientset: %v"
,
err
)
glog
.
Errorf
(
"Failed to create clientset: %v"
,
err
)
}
}
admissionController
:=
admission
.
NewFromPlugins
(
client
,
admissionControlPluginNames
,
s
.
AdmissionControlConfigFile
)
namespaceInformer
:=
informers
.
CreateSharedNamespaceIndexInformer
(
client
,
5
*
time
.
Minute
)
pluginInit
:=
admission
.
NewPluginInitializer
()
pluginInit
.
SetNamespaceInformer
(
namespaceInformer
)
admissionController
:=
admission
.
NewFromPlugins
(
client
,
admissionControlPluginNames
,
s
.
AdmissionControlConfigFile
)
genericConfig
:=
genericapiserver
.
NewConfig
(
s
)
genericConfig
:=
genericapiserver
.
NewConfig
(
s
)
// TODO: Move the following to generic api server as well.
// TODO: Move the following to generic api server as well.
genericConfig
.
StorageFactory
=
storageFactory
genericConfig
.
StorageFactory
=
storageFactory
...
...
pkg/admission/init.go
0 → 100644
View file @
fc0a3c6d
/*
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
admission
import
(
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/controller/framework"
"reflect"
)
// PluginInitializer is used for Initialization of shareable resources between admission plugins
// After Initialization the resources have to be set separately
type
PluginInitializer
interface
{
Initialize
(
plugins
[]
Interface
)
SetNamespaceInformer
(
namespaceInformer
framework
.
SharedIndexInformer
)
}
type
pluginInitializer
struct
{
informers
map
[
reflect
.
Type
]
framework
.
SharedIndexInformer
}
// NewPluginInitializer constructs new instance of PluginInitializer
func
NewPluginInitializer
()
PluginInitializer
{
plugInit
:=
&
pluginInitializer
{
informers
:
make
(
map
[
reflect
.
Type
]
framework
.
SharedIndexInformer
),
}
return
plugInit
}
// SetNamespaceInformer sets unique namespaceInformer for instance of PluginInitializer
func
(
i
*
pluginInitializer
)
SetNamespaceInformer
(
namespaceInformer
framework
.
SharedIndexInformer
)
{
i
.
informers
[
reflect
.
TypeOf
(
&
api
.
Namespace
{})]
=
namespaceInformer
}
// Initialize will check the initialization interfaces implemented by each plugin
// and provide the appropriate initialization data
func
(
i
*
pluginInitializer
)
Initialize
(
plugins
[]
Interface
)
{
for
_
,
plugin
:=
range
plugins
{
if
wantsNamespaceInformer
,
ok
:=
plugin
.
(
WantsNamespaceInformer
);
ok
{
wantsNamespaceInformer
.
SetNamespaceInformer
(
i
.
informers
[
reflect
.
TypeOf
(
&
api
.
Namespace
{})])
}
}
}
// Validate will call the Validate function in each plugin if they implement
// the Validator interface.
func
Validate
(
plugins
[]
Interface
)
error
{
for
_
,
plugin
:=
range
plugins
{
if
validater
,
ok
:=
plugin
.
(
Validator
);
ok
{
err
:=
validater
.
Validate
()
if
err
!=
nil
{
return
err
}
}
}
return
nil
}
pkg/admission/types.go
0 → 100644
View file @
fc0a3c6d
/*
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
admission
import
"k8s.io/kubernetes/pkg/controller/framework"
// Validator holds Validate functions, which are responsible for validation of initialized shared resources
// and should be implemented on admission plugins
type
Validator
interface
{
Validate
()
error
}
// WantsNamespaceInformer defines a function witch sets NamespaceInformer for admission plugins that need it
type
WantsNamespaceInformer
interface
{
SetNamespaceInformer
(
framework
.
SharedIndexInformer
)
}
pkg/controller/framework/informers/factory.go
View file @
fc0a3c6d
...
@@ -118,3 +118,21 @@ func CreateSharedPVIndexInformer(client clientset.Interface, resyncPeriod time.D
...
@@ -118,3 +118,21 @@ func CreateSharedPVIndexInformer(client clientset.Interface, resyncPeriod time.D
return
sharedIndexInformer
return
sharedIndexInformer
}
}
// CreateSharedNamespaceIndexInformer returns a SharedIndexInformer that lists and watches namespaces
func
CreateSharedNamespaceIndexInformer
(
client
clientset
.
Interface
,
resyncPeriod
time
.
Duration
)
framework
.
SharedIndexInformer
{
sharedIndexInformer
:=
framework
.
NewSharedIndexInformer
(
&
cache
.
ListWatch
{
ListFunc
:
func
(
options
api
.
ListOptions
)
(
runtime
.
Object
,
error
)
{
return
client
.
Core
()
.
Namespaces
()
.
List
(
options
)
},
WatchFunc
:
func
(
options
api
.
ListOptions
)
(
watch
.
Interface
,
error
)
{
return
client
.
Core
()
.
Namespaces
()
.
Watch
(
options
)
},
},
&
api
.
Namespace
{},
resyncPeriod
,
cache
.
Indexers
{})
return
sharedIndexInformer
}
plugin/pkg/admission/namespace/autoprovision/admission.go
View file @
fc0a3c6d
...
@@ -21,12 +21,11 @@ import (
...
@@ -21,12 +21,11 @@ import (
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"fmt"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/controller/framework"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/watch"
)
)
func
init
()
{
func
init
()
{
...
@@ -40,10 +39,12 @@ func init() {
...
@@ -40,10 +39,12 @@ func init() {
// It is useful in deployments that do not want to restrict creation of a namespace prior to its usage.
// It is useful in deployments that do not want to restrict creation of a namespace prior to its usage.
type
provision
struct
{
type
provision
struct
{
*
admission
.
Handler
*
admission
.
Handler
client
clientset
.
Interface
client
clientset
.
Interface
store
cache
.
Store
informer
framework
.
SharedIndexInformer
}
}
var
_
=
admission
.
WantsNamespaceInformer
(
&
provision
{})
func
(
p
*
provision
)
Admit
(
a
admission
.
Attributes
)
(
err
error
)
{
func
(
p
*
provision
)
Admit
(
a
admission
.
Attributes
)
(
err
error
)
{
// if we're here, then we've already passed authentication, so we're allowed to do what we're trying to do
// if we're here, then we've already passed authentication, so we're allowed to do what we're trying to do
// if we're here, then the API server has found a route, which means that if we have a non-empty namespace
// if we're here, then the API server has found a route, which means that if we have a non-empty namespace
...
@@ -59,7 +60,7 @@ func (p *provision) Admit(a admission.Attributes) (err error) {
...
@@ -59,7 +60,7 @@ func (p *provision) Admit(a admission.Attributes) (err error) {
},
},
Status
:
api
.
NamespaceStatus
{},
Status
:
api
.
NamespaceStatus
{},
}
}
_
,
exists
,
err
:=
p
.
store
.
Get
(
namespace
)
_
,
exists
,
err
:=
p
.
informer
.
GetStore
()
.
Get
(
namespace
)
if
err
!=
nil
{
if
err
!=
nil
{
return
admission
.
NewForbidden
(
a
,
err
)
return
admission
.
NewForbidden
(
a
,
err
)
}
}
...
@@ -75,28 +76,19 @@ func (p *provision) Admit(a admission.Attributes) (err error) {
...
@@ -75,28 +76,19 @@ func (p *provision) Admit(a admission.Attributes) (err error) {
// NewProvision creates a new namespace provision admission control handler
// NewProvision creates a new namespace provision admission control handler
func
NewProvision
(
c
clientset
.
Interface
)
admission
.
Interface
{
func
NewProvision
(
c
clientset
.
Interface
)
admission
.
Interface
{
store
:=
cache
.
NewStore
(
cache
.
MetaNamespaceKeyFunc
)
reflector
:=
cache
.
NewReflector
(
&
cache
.
ListWatch
{
ListFunc
:
func
(
options
api
.
ListOptions
)
(
runtime
.
Object
,
error
)
{
return
c
.
Core
()
.
Namespaces
()
.
List
(
options
)
},
WatchFunc
:
func
(
options
api
.
ListOptions
)
(
watch
.
Interface
,
error
)
{
return
c
.
Core
()
.
Namespaces
()
.
Watch
(
options
)
},
},
&
api
.
Namespace
{},
store
,
0
,
)
reflector
.
Run
()
return
createProvision
(
c
,
store
)
}
func
createProvision
(
c
clientset
.
Interface
,
store
cache
.
Store
)
admission
.
Interface
{
return
&
provision
{
return
&
provision
{
Handler
:
admission
.
NewHandler
(
admission
.
Create
),
Handler
:
admission
.
NewHandler
(
admission
.
Create
),
client
:
c
,
client
:
c
,
store
:
store
,
}
}
}
}
func
(
p
*
provision
)
SetNamespaceInformer
(
c
framework
.
SharedIndexInformer
)
{
p
.
informer
=
c
}
func
(
p
*
provision
)
Validate
()
error
{
if
p
.
informer
==
nil
{
return
fmt
.
Errorf
(
"namespace autoprovision plugin needs a namespace informer"
)
}
return
nil
}
plugin/pkg/admission/namespace/autoprovision/admission_test.go
View file @
fc0a3c6d
...
@@ -18,13 +18,14 @@ package autoprovision
...
@@ -18,13 +18,14 @@ package autoprovision
import
(
import
(
"testing"
"testing"
"time"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/kubernetes/pkg/client/testing/core"
"k8s.io/kubernetes/pkg/client/testing/core"
"k8s.io/kubernetes/pkg/controller/framework/informers"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime"
)
)
...
@@ -33,8 +34,8 @@ func TestAdmission(t *testing.T) {
...
@@ -33,8 +34,8 @@ func TestAdmission(t *testing.T) {
namespace
:=
"test"
namespace
:=
"test"
mockClient
:=
&
fake
.
Clientset
{}
mockClient
:=
&
fake
.
Clientset
{}
handler
:=
&
provision
{
handler
:=
&
provision
{
client
:
mockClient
,
client
:
mockClient
,
store
:
cache
.
NewStore
(
cache
.
MetaNamespaceKeyFunc
),
informer
:
informers
.
CreateSharedNamespaceIndexInformer
(
mockClient
,
5
*
time
.
Minute
),
}
}
pod
:=
api
.
Pod
{
pod
:=
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespace
},
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespace
},
...
@@ -60,13 +61,13 @@ func TestAdmission(t *testing.T) {
...
@@ -60,13 +61,13 @@ func TestAdmission(t *testing.T) {
func
TestAdmissionNamespaceExists
(
t
*
testing
.
T
)
{
func
TestAdmissionNamespaceExists
(
t
*
testing
.
T
)
{
namespace
:=
"test"
namespace
:=
"test"
mockClient
:=
&
fake
.
Clientset
{}
mockClient
:=
&
fake
.
Clientset
{}
store
:=
cache
.
NewStore
(
cache
.
MetaNamespaceKeyFunc
)
informer
:=
informers
.
CreateSharedNamespaceIndexInformer
(
mockClient
,
5
*
time
.
Minute
)
store
.
Add
(
&
api
.
Namespace
{
informer
.
GetStore
()
.
Add
(
&
api
.
Namespace
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
namespace
},
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
namespace
},
})
})
handler
:=
&
provision
{
handler
:=
&
provision
{
client
:
mockClient
,
client
:
mockClient
,
store
:
store
,
informer
:
informer
,
}
}
pod
:=
api
.
Pod
{
pod
:=
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespace
},
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespace
},
...
@@ -88,7 +89,7 @@ func TestAdmissionNamespaceExists(t *testing.T) {
...
@@ -88,7 +89,7 @@ func TestAdmissionNamespaceExists(t *testing.T) {
func
TestIgnoreAdmission
(
t
*
testing
.
T
)
{
func
TestIgnoreAdmission
(
t
*
testing
.
T
)
{
namespace
:=
"test"
namespace
:=
"test"
mockClient
:=
&
fake
.
Clientset
{}
mockClient
:=
&
fake
.
Clientset
{}
handler
:=
admission
.
NewChainHandler
(
createProvision
(
mockClient
,
nil
))
handler
:=
admission
.
NewChainHandler
(
NewProvision
(
mockClient
))
pod
:=
api
.
Pod
{
pod
:=
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespace
},
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespace
},
Spec
:
api
.
PodSpec
{
Spec
:
api
.
PodSpec
{
...
@@ -113,10 +114,9 @@ func TestAdmissionNamespaceExistsUnknownToHandler(t *testing.T) {
...
@@ -113,10 +114,9 @@ func TestAdmissionNamespaceExistsUnknownToHandler(t *testing.T) {
return
true
,
nil
,
errors
.
NewAlreadyExists
(
api
.
Resource
(
"namespaces"
),
namespace
)
return
true
,
nil
,
errors
.
NewAlreadyExists
(
api
.
Resource
(
"namespaces"
),
namespace
)
})
})
store
:=
cache
.
NewStore
(
cache
.
MetaNamespaceKeyFunc
)
handler
:=
&
provision
{
handler
:=
&
provision
{
client
:
mockClient
,
client
:
mockClient
,
store
:
store
,
informer
:
informers
.
CreateSharedNamespaceIndexInformer
(
mockClient
,
5
*
time
.
Minute
)
,
}
}
pod
:=
api
.
Pod
{
pod
:=
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespace
},
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespace
},
...
@@ -130,3 +130,17 @@ func TestAdmissionNamespaceExistsUnknownToHandler(t *testing.T) {
...
@@ -130,3 +130,17 @@ func TestAdmissionNamespaceExistsUnknownToHandler(t *testing.T) {
t
.
Errorf
(
"Unexpected error returned from admission handler"
)
t
.
Errorf
(
"Unexpected error returned from admission handler"
)
}
}
}
}
// TestAdmissionNamespaceValidate
func
TestAdmissionNamespaceValidate
(
t
*
testing
.
T
)
{
mockClient
:=
&
fake
.
Clientset
{}
informer
:=
informers
.
CreateSharedNamespaceIndexInformer
(
mockClient
,
5
*
time
.
Minute
)
handler
:=
&
provision
{
client
:
mockClient
,
}
handler
.
SetNamespaceInformer
(
informer
)
err
:=
handler
.
Validate
()
if
err
!=
nil
{
t
.
Errorf
(
"Failed to initialize informer"
)
}
}
plugin/pkg/admission/namespace/exists/admission.go
View file @
fc0a3c6d
...
@@ -18,16 +18,14 @@ package exists
...
@@ -18,16 +18,14 @@ package exists
import
(
import
(
"io"
"io"
"time"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"fmt"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/controller/framework"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/watch"
)
)
func
init
()
{
func
init
()
{
...
@@ -41,10 +39,12 @@ func init() {
...
@@ -41,10 +39,12 @@ func init() {
// It is useful in deployments that want to enforce pre-declaration of a Namespace resource.
// It is useful in deployments that want to enforce pre-declaration of a Namespace resource.
type
exists
struct
{
type
exists
struct
{
*
admission
.
Handler
*
admission
.
Handler
client
clientset
.
Interface
client
clientset
.
Interface
store
cache
.
Store
informer
framework
.
SharedIndexInformer
}
}
var
_
=
admission
.
WantsNamespaceInformer
(
&
exists
{})
func
(
e
*
exists
)
Admit
(
a
admission
.
Attributes
)
(
err
error
)
{
func
(
e
*
exists
)
Admit
(
a
admission
.
Attributes
)
(
err
error
)
{
// if we're here, then we've already passed authentication, so we're allowed to do what we're trying to do
// if we're here, then we've already passed authentication, so we're allowed to do what we're trying to do
// if we're here, then the API server has found a route, which means that if we have a non-empty namespace
// if we're here, then the API server has found a route, which means that if we have a non-empty namespace
...
@@ -60,7 +60,7 @@ func (e *exists) Admit(a admission.Attributes) (err error) {
...
@@ -60,7 +60,7 @@ func (e *exists) Admit(a admission.Attributes) (err error) {
},
},
Status
:
api
.
NamespaceStatus
{},
Status
:
api
.
NamespaceStatus
{},
}
}
_
,
exists
,
err
:=
e
.
store
.
Get
(
namespace
)
_
,
exists
,
err
:=
e
.
informer
.
GetStore
()
.
Get
(
namespace
)
if
err
!=
nil
{
if
err
!=
nil
{
return
errors
.
NewInternalError
(
err
)
return
errors
.
NewInternalError
(
err
)
}
}
...
@@ -82,24 +82,19 @@ func (e *exists) Admit(a admission.Attributes) (err error) {
...
@@ -82,24 +82,19 @@ func (e *exists) Admit(a admission.Attributes) (err error) {
// NewExists creates a new namespace exists admission control handler
// NewExists creates a new namespace exists admission control handler
func
NewExists
(
c
clientset
.
Interface
)
admission
.
Interface
{
func
NewExists
(
c
clientset
.
Interface
)
admission
.
Interface
{
store
:=
cache
.
NewStore
(
cache
.
MetaNamespaceKeyFunc
)
reflector
:=
cache
.
NewReflector
(
&
cache
.
ListWatch
{
ListFunc
:
func
(
options
api
.
ListOptions
)
(
runtime
.
Object
,
error
)
{
return
c
.
Core
()
.
Namespaces
()
.
List
(
options
)
},
WatchFunc
:
func
(
options
api
.
ListOptions
)
(
watch
.
Interface
,
error
)
{
return
c
.
Core
()
.
Namespaces
()
.
Watch
(
options
)
},
},
&
api
.
Namespace
{},
store
,
5
*
time
.
Minute
,
)
reflector
.
Run
()
return
&
exists
{
return
&
exists
{
client
:
c
,
client
:
c
,
store
:
store
,
Handler
:
admission
.
NewHandler
(
admission
.
Create
,
admission
.
Update
,
admission
.
Delete
),
Handler
:
admission
.
NewHandler
(
admission
.
Create
,
admission
.
Update
,
admission
.
Delete
),
}
}
}
}
func
(
e
*
exists
)
SetNamespaceInformer
(
c
framework
.
SharedIndexInformer
)
{
e
.
informer
=
c
}
func
(
e
*
exists
)
Validate
()
error
{
if
e
.
informer
==
nil
{
return
fmt
.
Errorf
(
"namespace exists plugin needs a namespace informer"
)
}
return
nil
}
plugin/pkg/admission/namespace/lifecycle/admission.go
View file @
fc0a3c6d
...
@@ -19,17 +19,14 @@ package lifecycle
...
@@ -19,17 +19,14 @@ package lifecycle
import
(
import
(
"fmt"
"fmt"
"io"
"io"
"time"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/controller/framework"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/watch"
)
)
const
PluginName
=
"NamespaceLifecycle"
const
PluginName
=
"NamespaceLifecycle"
...
@@ -45,10 +42,12 @@ func init() {
...
@@ -45,10 +42,12 @@ func init() {
type
lifecycle
struct
{
type
lifecycle
struct
{
*
admission
.
Handler
*
admission
.
Handler
client
clientset
.
Interface
client
clientset
.
Interface
store
cache
.
Store
informer
framework
.
SharedIndexInformer
immortalNamespaces
sets
.
String
immortalNamespaces
sets
.
String
}
}
var
_
=
admission
.
WantsNamespaceInformer
(
&
lifecycle
{})
func
(
l
*
lifecycle
)
Admit
(
a
admission
.
Attributes
)
(
err
error
)
{
func
(
l
*
lifecycle
)
Admit
(
a
admission
.
Attributes
)
(
err
error
)
{
// prevent deletion of immortal namespaces
// prevent deletion of immortal namespaces
if
a
.
GetOperation
()
==
admission
.
Delete
&&
a
.
GetKind
()
.
GroupKind
()
==
api
.
Kind
(
"Namespace"
)
&&
l
.
immortalNamespaces
.
Has
(
a
.
GetName
())
{
if
a
.
GetOperation
()
==
admission
.
Delete
&&
a
.
GetKind
()
.
GroupKind
()
==
api
.
Kind
(
"Namespace"
)
&&
l
.
immortalNamespaces
.
Has
(
a
.
GetName
())
{
...
@@ -65,7 +64,7 @@ func (l *lifecycle) Admit(a admission.Attributes) (err error) {
...
@@ -65,7 +64,7 @@ func (l *lifecycle) Admit(a admission.Attributes) (err error) {
// this will cause a live lookup of the namespace to get its latest state even
// this will cause a live lookup of the namespace to get its latest state even
// before the watch notification is received.
// before the watch notification is received.
if
a
.
GetOperation
()
==
admission
.
Delete
{
if
a
.
GetOperation
()
==
admission
.
Delete
{
l
.
store
.
Delete
(
&
api
.
Namespace
{
l
.
informer
.
GetStore
()
.
Delete
(
&
api
.
Namespace
{
ObjectMeta
:
api
.
ObjectMeta
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
a
.
GetName
(),
Name
:
a
.
GetName
(),
},
},
...
@@ -74,7 +73,7 @@ func (l *lifecycle) Admit(a admission.Attributes) (err error) {
...
@@ -74,7 +73,7 @@ func (l *lifecycle) Admit(a admission.Attributes) (err error) {
return
nil
return
nil
}
}
namespaceObj
,
exists
,
err
:=
l
.
store
.
Get
(
&
api
.
Namespace
{
namespaceObj
,
exists
,
err
:=
l
.
informer
.
GetStore
()
.
Get
(
&
api
.
Namespace
{
ObjectMeta
:
api
.
ObjectMeta
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
a
.
GetNamespace
(),
Name
:
a
.
GetNamespace
(),
Namespace
:
""
,
Namespace
:
""
,
...
@@ -112,25 +111,19 @@ func (l *lifecycle) Admit(a admission.Attributes) (err error) {
...
@@ -112,25 +111,19 @@ func (l *lifecycle) Admit(a admission.Attributes) (err error) {
// NewLifecycle creates a new namespace lifecycle admission control handler
// NewLifecycle creates a new namespace lifecycle admission control handler
func
NewLifecycle
(
c
clientset
.
Interface
,
immortalNamespaces
sets
.
String
)
admission
.
Interface
{
func
NewLifecycle
(
c
clientset
.
Interface
,
immortalNamespaces
sets
.
String
)
admission
.
Interface
{
store
:=
cache
.
NewStore
(
cache
.
MetaNamespaceKeyFunc
)
reflector
:=
cache
.
NewReflector
(
&
cache
.
ListWatch
{
ListFunc
:
func
(
options
api
.
ListOptions
)
(
runtime
.
Object
,
error
)
{
return
c
.
Core
()
.
Namespaces
()
.
List
(
options
)
},
WatchFunc
:
func
(
options
api
.
ListOptions
)
(
watch
.
Interface
,
error
)
{
return
c
.
Core
()
.
Namespaces
()
.
Watch
(
options
)
},
},
&
api
.
Namespace
{},
store
,
5
*
time
.
Minute
,
)
reflector
.
Run
()
return
&
lifecycle
{
return
&
lifecycle
{
Handler
:
admission
.
NewHandler
(
admission
.
Create
,
admission
.
Update
,
admission
.
Delete
),
Handler
:
admission
.
NewHandler
(
admission
.
Create
,
admission
.
Update
,
admission
.
Delete
),
client
:
c
,
client
:
c
,
store
:
store
,
immortalNamespaces
:
immortalNamespaces
,
immortalNamespaces
:
immortalNamespaces
,
}
}
}
}
func
(
l
*
lifecycle
)
SetNamespaceInformer
(
c
framework
.
SharedIndexInformer
)
{
l
.
informer
=
c
}
func
(
l
*
lifecycle
)
Validate
()
error
{
if
l
.
informer
==
nil
{
return
fmt
.
Errorf
(
"namespace lifecycle plugin needs a namespace informer"
)
}
return
nil
}
plugin/pkg/admission/namespace/lifecycle/admission_test.go
View file @
fc0a3c6d
...
@@ -20,13 +20,14 @@ import (
...
@@ -20,13 +20,14 @@ import (
"fmt"
"fmt"
"sync"
"sync"
"testing"
"testing"
"time"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/kubernetes/pkg/client/testing/core"
"k8s.io/kubernetes/pkg/client/testing/core"
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
"k8s.io/kubernetes/pkg/controller/framework/informers"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/sets"
)
)
...
@@ -44,9 +45,10 @@ func TestAdmission(t *testing.T) {
...
@@ -44,9 +45,10 @@ func TestAdmission(t *testing.T) {
}
}
var
namespaceLock
sync
.
RWMutex
var
namespaceLock
sync
.
RWMutex
store
:=
cache
.
NewStore
(
cache
.
MetaNamespaceKeyFunc
)
store
.
Add
(
namespaceObj
)
mockClient
:=
fake
.
NewSimpleClientset
()
mockClient
:=
fake
.
NewSimpleClientset
()
informer
:=
informers
.
CreateSharedNamespaceIndexInformer
(
mockClient
,
5
*
time
.
Minute
)
informer
.
GetStore
()
.
Add
(
namespaceObj
)
mockClient
.
PrependReactor
(
"get"
,
"namespaces"
,
func
(
action
core
.
Action
)
(
bool
,
runtime
.
Object
,
error
)
{
mockClient
.
PrependReactor
(
"get"
,
"namespaces"
,
func
(
action
core
.
Action
)
(
bool
,
runtime
.
Object
,
error
)
{
namespaceLock
.
RLock
()
namespaceLock
.
RLock
()
defer
namespaceLock
.
RUnlock
()
defer
namespaceLock
.
RUnlock
()
...
@@ -62,7 +64,7 @@ func TestAdmission(t *testing.T) {
...
@@ -62,7 +64,7 @@ func TestAdmission(t *testing.T) {
})
})
lfhandler
:=
NewLifecycle
(
mockClient
,
sets
.
NewString
(
"default"
))
.
(
*
lifecycle
)
lfhandler
:=
NewLifecycle
(
mockClient
,
sets
.
NewString
(
"default"
))
.
(
*
lifecycle
)
lfhandler
.
store
=
store
lfhandler
.
informer
=
informer
handler
:=
admission
.
NewChainHandler
(
lfhandler
)
handler
:=
admission
.
NewChainHandler
(
lfhandler
)
pod
:=
api
.
Pod
{
pod
:=
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespaceObj
.
Name
},
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespaceObj
.
Name
},
...
@@ -87,7 +89,7 @@ func TestAdmission(t *testing.T) {
...
@@ -87,7 +89,7 @@ func TestAdmission(t *testing.T) {
namespaceLock
.
Lock
()
namespaceLock
.
Lock
()
namespaceObj
.
Status
.
Phase
=
api
.
NamespaceTerminating
namespaceObj
.
Status
.
Phase
=
api
.
NamespaceTerminating
namespaceLock
.
Unlock
()
namespaceLock
.
Unlock
()
store
.
Add
(
namespaceObj
)
informer
.
GetStore
()
.
Add
(
namespaceObj
)
// verify create operations in the namespace cause an error
// verify create operations in the namespace cause an error
err
=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
&
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
pod
.
Namespace
,
pod
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
))
err
=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
&
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
pod
.
Namespace
,
pod
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
))
...
...
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