diff --git a/hack/.linted_packages b/hack/.linted_packages index 01d43460ee74..7d7e85a02023 100644 --- a/hack/.linted_packages +++ b/hack/.linted_packages @@ -304,6 +304,7 @@ staging/src/k8s.io/apimachinery/pkg/util/json staging/src/k8s.io/apimachinery/pkg/util/validation/field staging/src/k8s.io/apimachinery/pkg/version staging/src/k8s.io/apimachinery/pkg/watch +staging/src/k8s.io/apiserver/pkg/admission/initializer staging/src/k8s.io/apiserver/pkg/apis/apiserver/install staging/src/k8s.io/apiserver/pkg/apis/example/install staging/src/k8s.io/apiserver/pkg/authentication/authenticator diff --git a/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer.go b/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer.go new file mode 100644 index 000000000000..c0b1e1d25b75 --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer.go @@ -0,0 +1,57 @@ +/* +Copyright 2017 The Kubernetes Authors. + +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 initializer + +import ( + "k8s.io/apiserver/pkg/admission" + "k8s.io/apiserver/pkg/authorization/authorizer" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" +) + +type pluginInitializer struct { + externalClient kubernetes.Interface + externalInformers informers.SharedInformerFactory + authorizer authorizer.Authorizer +} + +// New creates an instance of admission plugins initializer. +func New(extClientset kubernetes.Interface, extInformers informers.SharedInformerFactory, authz authorizer.Authorizer) (pluginInitializer, error) { + return pluginInitializer{ + externalClient: extClientset, + externalInformers: extInformers, + authorizer: authz, + }, nil +} + +// Initialize checks the initialization interfaces implemented by a plugin +// and provide the appropriate initialization data +func (i pluginInitializer) Initialize(plugin admission.Interface) { + if wants, ok := plugin.(WantsExternalKubeClientSet); ok { + wants.SetExternalKubeClientSet(i.externalClient) + } + + if wants, ok := plugin.(WantsExternalKubeInformerFactory); ok { + wants.SetExternalKubeInformerFactory(i.externalInformers) + } + + if wants, ok := plugin.(WantsAuthorizer); ok { + wants.SetAuthorizer(i.authorizer) + } +} + +var _ admission.PluginInitializer = pluginInitializer{} diff --git a/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer_test.go b/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer_test.go new file mode 100644 index 000000000000..03540d907ff3 --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer_test.go @@ -0,0 +1,122 @@ +/* +Copyright 2017 The Kubernetes Authors. + +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 initializer_test + +import ( + "testing" + "time" + + "k8s.io/apiserver/pkg/admission" + "k8s.io/apiserver/pkg/admission/initializer" + "k8s.io/apiserver/pkg/authorization/authorizer" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/fake" +) + +// TestWantsAuthorizer ensures that the authorizer is injected +// when the WantsAuthorizer interface is implemented by a plugin. +func TestWantsAuthorizer(t *testing.T) { + target, err := initializer.New(nil, nil, &TestAuthorizer{}) + if err != nil { + t.Fatalf("expected to create an instance of initializer but got an error = %s", err.Error()) + } + wantAuthorizerAdmission := &WantAuthorizerAdmission{} + target.Initialize(wantAuthorizerAdmission) + if wantAuthorizerAdmission.auth == nil { + t.Errorf("expected authorizer to be initialized but found nil") + } +} + +// TestWantsExternalKubeClientSet ensures that the clienset is injected +// when the WantsExternalKubeClientSet interface is implemented by a plugin. +func TestWantsExternalKubeClientSet(t *testing.T) { + cs := &fake.Clientset{} + target, err := initializer.New(cs, nil, &TestAuthorizer{}) + if err != nil { + t.Fatalf("expected to create an instance of initializer but got an error = %s", err.Error()) + } + wantExternalKubeClientSet := &WantExternalKubeClientSet{} + target.Initialize(wantExternalKubeClientSet) + if wantExternalKubeClientSet.cs != cs { + t.Errorf("expected clientset to be initialized") + } +} + +// TestWantsExternalKubeInformerFactory ensures that the informer factory is injected +// when the WantsExternalKubeInformerFactory interface is implemented by a plugin. +func TestWantsExternalKubeInformerFactory(t *testing.T) { + cs := &fake.Clientset{} + sf := informers.NewSharedInformerFactory(cs, time.Duration(1)*time.Second) + target, err := initializer.New(cs, sf, &TestAuthorizer{}) + if err != nil { + t.Fatalf("expected to create an instance of initializer but got an error = %s", err.Error()) + } + wantExternalKubeInformerFactory := &WantExternalKubeInformerFactory{} + target.Initialize(wantExternalKubeInformerFactory) + if wantExternalKubeInformerFactory.sf != sf { + t.Errorf("expected informer factory to be initialized") + } +} + +// WantExternalKubeInformerFactory is a test stub that fulfills the WantsExternalKubeInformerFactory interface +type WantExternalKubeInformerFactory struct { + sf informers.SharedInformerFactory +} + +func (self *WantExternalKubeInformerFactory) SetExternalKubeInformerFactory(sf informers.SharedInformerFactory) { + self.sf = sf +} +func (self *WantExternalKubeInformerFactory) Admit(a admission.Attributes) error { return nil } +func (self *WantExternalKubeInformerFactory) Handles(o admission.Operation) bool { return false } +func (self *WantExternalKubeInformerFactory) Validate() error { return nil } + +var _ admission.Interface = &WantExternalKubeInformerFactory{} +var _ initializer.WantsExternalKubeInformerFactory = &WantExternalKubeInformerFactory{} + +// WantExternalKubeClientSet is a test stub that fulfills the WantsExternalKubeClientSet interface +type WantExternalKubeClientSet struct { + cs kubernetes.Interface +} + +func (self *WantExternalKubeClientSet) SetExternalKubeClientSet(cs kubernetes.Interface) { self.cs = cs } +func (self *WantExternalKubeClientSet) Admit(a admission.Attributes) error { return nil } +func (self *WantExternalKubeClientSet) Handles(o admission.Operation) bool { return false } +func (self *WantExternalKubeClientSet) Validate() error { return nil } + +var _ admission.Interface = &WantExternalKubeClientSet{} +var _ initializer.WantsExternalKubeClientSet = &WantExternalKubeClientSet{} + +// WantAuthorizerAdmission is a test stub that fulfills the WantsAuthorizer interface. +type WantAuthorizerAdmission struct { + auth authorizer.Authorizer +} + +func (self *WantAuthorizerAdmission) SetAuthorizer(a authorizer.Authorizer) { self.auth = a } +func (self *WantAuthorizerAdmission) Admit(a admission.Attributes) error { return nil } +func (self *WantAuthorizerAdmission) Handles(o admission.Operation) bool { return false } +func (self *WantAuthorizerAdmission) Validate() error { return nil } + +var _ admission.Interface = &WantAuthorizerAdmission{} +var _ initializer.WantsAuthorizer = &WantAuthorizerAdmission{} + +// TestAuthorizer is a test stub for testing that fulfills the authorizer interface. +type TestAuthorizer struct{} + +func (t *TestAuthorizer) Authorize(a authorizer.Attributes) (authorized bool, reason string, err error) { + return false, "", nil +} diff --git a/staging/src/k8s.io/apiserver/pkg/admission/initializer/interfaces.go b/staging/src/k8s.io/apiserver/pkg/admission/initializer/interfaces.go new file mode 100644 index 000000000000..a216c9888fab --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/admission/initializer/interfaces.go @@ -0,0 +1,42 @@ +/* +Copyright 2017 The Kubernetes Authors. + +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 initializer + +import ( + "k8s.io/apiserver/pkg/admission" + "k8s.io/apiserver/pkg/authorization/authorizer" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" +) + +// WantsExternalKubeClientSet defines a function which sets external ClientSet for admission plugins that need it +type WantsExternalKubeClientSet interface { + SetExternalKubeClientSet(kubernetes.Interface) + admission.Validator +} + +// WantsExternalKubeInformerFactory defines a function which sets InformerFactory for admission plugins that need it +type WantsExternalKubeInformerFactory interface { + SetExternalKubeInformerFactory(informers.SharedInformerFactory) + admission.Validator +} + +// WantsAuthorizer defines a function which sets Authorizer for admission plugins that need it. +type WantsAuthorizer interface { + SetAuthorizer(authorizer.Authorizer) + admission.Validator +} diff --git a/vendor/BUILD b/vendor/BUILD index 5d24c0c58531..308c4eb0d78e 100644 --- a/vendor/BUILD +++ b/vendor/BUILD @@ -16400,3 +16400,32 @@ go_library( "//vendor:k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion", ], ) + +go_library( + name = "k8s.io/apiserver/pkg/admission/initializer", + srcs = [ + "k8s.io/apiserver/pkg/admission/initializer/initializer.go", + "k8s.io/apiserver/pkg/admission/initializer/interfaces.go", + ], + tags = ["automanaged"], + deps = [ + "//vendor:k8s.io/apiserver/pkg/admission", + "//vendor:k8s.io/apiserver/pkg/authorization/authorizer", + "//vendor:k8s.io/client-go/informers", + "//vendor:k8s.io/client-go/kubernetes", + ], +) + +go_test( + name = "k8s.io/apiserver/pkg/admission/initializer_xtest", + srcs = ["k8s.io/apiserver/pkg/admission/initializer/initializer_test.go"], + tags = ["automanaged"], + deps = [ + "//vendor:k8s.io/apiserver/pkg/admission", + "//vendor:k8s.io/apiserver/pkg/admission/initializer", + "//vendor:k8s.io/apiserver/pkg/authorization/authorizer", + "//vendor:k8s.io/client-go/informers", + "//vendor:k8s.io/client-go/kubernetes", + "//vendor:k8s.io/client-go/kubernetes/fake", + ], +)