From af5379485411214d0a1f90c7974621b0f809afb3 Mon Sep 17 00:00:00 2001 From: Avesh Agarwal Date: Mon, 27 Feb 2017 13:34:46 -0500 Subject: [PATCH 1/3] Pod toleration restriction plugin with taints and tolerations. --- cmd/kube-apiserver/app/plugins.go | 1 + pkg/api/validation/validation.go | 10 +- pkg/util/tolerations/doc.go | 18 ++ pkg/util/tolerations/tolerations.go | 125 ++++++++++ pkg/util/tolerations/tolerations_test.go | 82 +++++++ .../podtolerationrestriction/admission.go | 221 ++++++++++++++++++ .../admission_test.go | 200 ++++++++++++++++ .../apis/podtolerationrestriction/OWNERS | 2 + .../apis/podtolerationrestriction/doc.go | 19 ++ .../install/install.go | 44 ++++ .../apis/podtolerationrestriction/register.go | 52 +++++ .../apis/podtolerationrestriction/types.go | 33 +++ .../v1alpha1/defaults.go | 28 +++ .../podtolerationrestriction/v1alpha1/doc.go | 23 ++ .../v1alpha1/register.go | 42 ++++ .../v1alpha1/types.go | 33 +++ .../validation/validation.go | 37 +++ .../validation/validation_test.go | 74 ++++++ .../podtolerationrestriction/config.go | 78 +++++++ 19 files changed, 1117 insertions(+), 5 deletions(-) create mode 100644 pkg/util/tolerations/doc.go create mode 100644 pkg/util/tolerations/tolerations.go create mode 100644 pkg/util/tolerations/tolerations_test.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/admission.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/admission_test.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/OWNERS create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/doc.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/install.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/register.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/types.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/defaults.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/doc.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/register.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/types.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation/validation.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation/validation_test.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/config.go diff --git a/cmd/kube-apiserver/app/plugins.go b/cmd/kube-apiserver/app/plugins.go index ad85f1e51d0..f5d524ab6d8 100644 --- a/cmd/kube-apiserver/app/plugins.go +++ b/cmd/kube-apiserver/app/plugins.go @@ -40,6 +40,7 @@ import ( _ "k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label" _ "k8s.io/kubernetes/plugin/pkg/admission/podnodeselector" _ "k8s.io/kubernetes/plugin/pkg/admission/podpreset" + _ "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction" _ "k8s.io/kubernetes/plugin/pkg/admission/resourcequota" _ "k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy" _ "k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny" diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index 1d17daffac7..ef4f8ce6c26 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -155,7 +155,7 @@ func ValidateTolerationsInPodAnnotations(annotations map[string]string, fldPath } if len(tolerations) > 0 { - allErrs = append(allErrs, validateTolerations(tolerations, fldPath.Child(api.TolerationsAnnotationKey))...) + allErrs = append(allErrs, ValidateTolerations(tolerations, fldPath.Child(api.TolerationsAnnotationKey))...) } return allErrs @@ -2000,12 +2000,12 @@ func validateOnlyAddedTolerations(newTolerations []api.Toleration, oldToleration } } - allErrs = append(allErrs, validateTolerations(newTolerations, fldPath)...) + allErrs = append(allErrs, ValidateTolerations(newTolerations, fldPath)...) return allErrs } -// validateTolerations tests if given tolerations have valid data. -func validateTolerations(tolerations []api.Toleration, fldPath *field.Path) field.ErrorList { +// ValidateTolerations tests if given tolerations have valid data. +func ValidateTolerations(tolerations []api.Toleration, fldPath *field.Path) field.ErrorList { allErrors := field.ErrorList{} for i, toleration := range tolerations { idxPath := fldPath.Index(i) @@ -2102,7 +2102,7 @@ func ValidatePodSpec(spec *api.PodSpec, fldPath *field.Path) field.ErrorList { } if len(spec.Tolerations) > 0 { - allErrs = append(allErrs, validateTolerations(spec.Tolerations, fldPath.Child("tolerations"))...) + allErrs = append(allErrs, ValidateTolerations(spec.Tolerations, fldPath.Child("tolerations"))...) } return allErrs diff --git a/pkg/util/tolerations/doc.go b/pkg/util/tolerations/doc.go new file mode 100644 index 00000000000..09fa857ab42 --- /dev/null +++ b/pkg/util/tolerations/doc.go @@ -0,0 +1,18 @@ +/* +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 tolerations provides utilities to work with pod spec tolerations. +package tolerations // import "k8s.io/kubernetes/pkg/util/tolerations" diff --git a/pkg/util/tolerations/tolerations.go b/pkg/util/tolerations/tolerations.go new file mode 100644 index 00000000000..9936d2d43ea --- /dev/null +++ b/pkg/util/tolerations/tolerations.go @@ -0,0 +1,125 @@ +/* +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 tolerations + +import ( + "k8s.io/kubernetes/pkg/api" +) + +type key struct { + tolerationKey string + effect api.TaintEffect +} + +// VerifyAgainstWhitelist checks if the provided tolerations +// satisfy the provided whitelist and returns true, otherwise returns false +func VerifyAgainstWhitelist(tolerations []api.Toleration, whitelist []api.Toleration) bool { + if len(whitelist) == 0 { + return true + } + + t := ConvertTolerationToAMap(tolerations) + w := ConvertTolerationToAMap(whitelist) + + for k1, v1 := range t { + if v2, ok := w[k1]; !ok || !AreEqual(v1, v2) { + return false + } + } + return true +} + +// IsConflict returns true if the key of two tolerations match +// but one or more other fields differ, otherwise returns false +func IsConflict(first []api.Toleration, second []api.Toleration) bool { + firstMap := ConvertTolerationToAMap(first) + secondMap := ConvertTolerationToAMap(second) + + for k1, v1 := range firstMap { + if v2, ok := secondMap[k1]; ok && !AreEqual(v1, v2) { + return true + } + } + return false +} + +// MergeTolerations merges two sets of tolerations into one +// it does not check for conflicts +func MergeTolerations(first []api.Toleration, second []api.Toleration) []api.Toleration { + var mergedTolerations []api.Toleration + mergedTolerations = append(mergedTolerations, second...) + + firstMap := ConvertTolerationToAMap(first) + secondMap := ConvertTolerationToAMap(second) + + for k1, v1 := range firstMap { + if _, ok := secondMap[k1]; !ok { + mergedTolerations = append(mergedTolerations, v1) + } + } + return mergedTolerations +} + +// EqualTolerations returns true if two sets of tolerations are equal, otherwise false +// it assumes no duplicates in individual set of tolerations +func EqualTolerations(first []api.Toleration, second []api.Toleration) bool { + if len(first) != len(second) { + return false + } + + firstMap := ConvertTolerationToAMap(first) + secondMap := ConvertTolerationToAMap(second) + + for k1, v1 := range firstMap { + if v2, ok := secondMap[k1]; !ok || !AreEqual(v1, v2) { + return false + } + } + return true +} + +// ConvertTolerationToAMap converts toleration list into a map[string]api.Toleration +func ConvertTolerationToAMap(in []api.Toleration) map[key]api.Toleration { + out := map[key]api.Toleration{} + for i := range in { + out[key{in[i].Key, in[i].Effect}] = in[i] + } + return out +} + +// AreEqual checks if two provided tolerations are equal or not. +func AreEqual(first, second api.Toleration) bool { + if first.Key == second.Key && + first.Operator == second.Operator && + first.Value == second.Value && + first.Effect == second.Effect && + AreTolerationSecondsEqual(first.TolerationSeconds, second.TolerationSeconds) { + return true + } + return false +} + +// AreTolerationSecondsEqual checks if two provided TolerationSeconds are equal or not. +func AreTolerationSecondsEqual(ts1, ts2 *int64) bool { + if ts1 == ts2 { + return true + } + if ts1 != nil && ts2 != nil && *ts1 == *ts2 { + return true + } + return false +} diff --git a/pkg/util/tolerations/tolerations_test.go b/pkg/util/tolerations/tolerations_test.go new file mode 100644 index 00000000000..e652baf357c --- /dev/null +++ b/pkg/util/tolerations/tolerations_test.go @@ -0,0 +1,82 @@ +/* +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 tolerations + +import ( + "testing" + + "k8s.io/kubernetes/pkg/api" +) + +func TestVerifyAgainstWhitelist(t *testing.T) { + tests := []struct { + input []api.Toleration + whitelist []api.Toleration + testName string + testStatus bool + }{ + { + input: []api.Toleration{{Key: "foo", Operator: "Equal", Value: "bar", Effect: "NoSchedule"}}, + whitelist: []api.Toleration{{Key: "foo", Operator: "Equal", Value: "bar", Effect: "NoSchedule"}}, + testName: "equal input and whitelist", + testStatus: true, + }, + { + input: []api.Toleration{{Key: "foo", Operator: "Equal", Value: "bar", Effect: "NoSchedule"}}, + whitelist: []api.Toleration{{Key: "foo", Operator: "Equal", Value: "bar", Effect: "NoExecute"}}, + testName: "input does not exist in whitelist", + testStatus: false, + }, + } + + for _, c := range tests { + status := VerifyAgainstWhitelist(c.input, c.whitelist) + if status != c.testStatus { + t.Errorf("Test: %s, expected %v", c.testName, status) + } + } + +} + +func TestIsConflict(t *testing.T) { + tests := []struct { + input1 []api.Toleration + input2 []api.Toleration + testName string + testStatus bool + }{ + { + input1: []api.Toleration{{Key: "foo", Operator: "Equal", Value: "bar", Effect: "NoSchedule"}}, + input2: []api.Toleration{{Key: "foo", Operator: "Equal", Value: "bar", Effect: "NoSchedule"}}, + testName: "equal inputs", + testStatus: true, + }, + { + input1: []api.Toleration{{Key: "foo", Operator: "Equal", Value: "foo", Effect: "NoExecute"}}, + input2: []api.Toleration{{Key: "foo", Operator: "Equal", Value: "bar", Effect: "NoExecute"}}, + testName: "mismatch values in inputs", + testStatus: false, + }, + } + + for _, c := range tests { + status := IsConflict(c.input1, c.input2) + if status == c.testStatus { + t.Errorf("Test: %s, expected %v", c.testName, status) + } + } +} diff --git a/plugin/pkg/admission/podtolerationrestriction/admission.go b/plugin/pkg/admission/podtolerationrestriction/admission.go new file mode 100644 index 00000000000..3e46b4bd6ad --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/admission.go @@ -0,0 +1,221 @@ +/* +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 podtolerationrestriction + +import ( + "encoding/json" + "fmt" + "io" + + "github.com/golang/glog" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apiserver/pkg/admission" + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/v1" + clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" + corelisters "k8s.io/kubernetes/pkg/client/listers/core/internalversion" + kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" + "k8s.io/kubernetes/pkg/util/tolerations" + pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction" +) + +func init() { + admission.RegisterPlugin("PodTolerationRestriction", func(config io.Reader) (admission.Interface, error) { + pluginConfig, err := loadConfiguration(config) + if err != nil { + return nil, err + } + return NewPodTolerationsPlugin(pluginConfig), nil + }) +} + +// The annotation keys for default and whitelist of tolerations +const ( + NSDefaultTolerations string = "scheduler.alpha.kubernetes.io/defaultTolerations" + NSWLTolerations string = "scheduler.alpha.kubernetes.io/tolerationsWhitelist" +) + +var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&podTolerationsPlugin{}) + +type podTolerationsPlugin struct { + *admission.Handler + client clientset.Interface + namespaceLister corelisters.NamespaceLister + pluginConfig *pluginapi.Configuration +} + +// This plugin first verifies any conflict between a pod's tolerations and +// its namespace's tolerations, and rejects the pod if there's a conflict. +// If there's no conflict, the pod's tolerations are merged with its namespace's +// toleration. Resulting pod's tolerations are verified against its namespace's +// whitelist of tolerations. If the verification is successful, the pod is admitted +// otherwise rejected. If a namespace does not have associated default or whitelist +// of tolerations, then cluster level default or whitelist of tolerations are used +// instead if specified. Tolerations to a namespace are assigned via +// scheduler.alpha.kubernetes.io/defaultTolerations and scheduler.alpha.kubernetes.io/tolerationsWhitelist +// annotations keys. +func (p *podTolerationsPlugin) Admit(a admission.Attributes) error { + resource := a.GetResource().GroupResource() + if resource != api.Resource("pods") { + return nil + } + if a.GetSubresource() != "" { + // only run the checks below on pods proper and not subresources + return nil + } + + obj := a.GetObject() + pod, ok := obj.(*api.Pod) + if !ok { + glog.Errorf("expected pod but got %s", a.GetKind().Kind) + return nil + } + + if !p.WaitForReady() { + return admission.NewForbidden(a, fmt.Errorf("not yet ready to handle request")) + } + + nsName := a.GetNamespace() + namespace, err := p.namespaceLister.Get(nsName) + if errors.IsNotFound(err) { + // in case of latency in our caches, make a call direct to storage to verify that it truly exists or not + namespace, err = p.client.Core().Namespaces().Get(nsName, metav1.GetOptions{}) + if err != nil { + if errors.IsNotFound(err) { + return err + } + return errors.NewInternalError(err) + } + } else if err != nil { + return errors.NewInternalError(err) + } + + var finalTolerations []api.Toleration + if a.GetOperation() == admission.Create { + ts, err := p.getNamespaceDefaultTolerations(namespace) + if err != nil { + return err + } + + // If the namespace has not specified its default tolerations, + // fall back to cluster's default tolerations. + if len(ts) == 0 { + ts = p.pluginConfig.Default + } + + if len(ts) > 0 { + if len(pod.Spec.Tolerations) > 0 { + if tolerations.IsConflict(ts, pod.Spec.Tolerations) { + return fmt.Errorf("namespace tolerations and pod tolerations conflict") + } + + // modified pod tolerations = namespace tolerations + current pod tolerations + finalTolerations = tolerations.MergeTolerations(ts, pod.Spec.Tolerations) + } else { + finalTolerations = ts + + } + } else { + finalTolerations = pod.Spec.Tolerations + } + } else { + finalTolerations = pod.Spec.Tolerations + } + + // whitelist verification. + if len(finalTolerations) > 0 { + whitelist, err := p.getNamespaceTolerationsWhitelist(namespace) + if err != nil { + return err + } + + // If the namespace has not specified its tolerations whitelist, + // fall back to cluster's whitelist of tolerations. + if len(whitelist) == 0 { + whitelist = p.pluginConfig.Whitelist + } + + if len(whitelist) > 0 { + // check if the merged pod tolerations satisfy its namespace whitelist + if !tolerations.VerifyAgainstWhitelist(finalTolerations, whitelist) { + return fmt.Errorf("pod tolerations (possibly merged with namespace default tolerations) conflict with its namespace whitelist") + } + } + } + + pod.Spec.Tolerations = finalTolerations + return nil + +} + +func NewPodTolerationsPlugin(pluginConfig *pluginapi.Configuration) *podTolerationsPlugin { + return &podTolerationsPlugin{ + Handler: admission.NewHandler(admission.Create, admission.Update), + pluginConfig: pluginConfig, + } +} + +func (a *podTolerationsPlugin) SetInternalKubeClientSet(client clientset.Interface) { + a.client = client +} + +func (p *podTolerationsPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { + namespaceInformer := f.Core().InternalVersion().Namespaces() + p.namespaceLister = namespaceInformer.Lister() + p.SetReadyFunc(namespaceInformer.Informer().HasSynced) + +} + +func (p *podTolerationsPlugin) Validate() error { + if p.namespaceLister == nil { + return fmt.Errorf("missing namespaceLister") + } + if p.client == nil { + return fmt.Errorf("missing client") + } + return nil +} + +func (p *podTolerationsPlugin) getNamespaceDefaultTolerations(ns *api.Namespace) ([]api.Toleration, error) { + return extractNSTolerations(ns, NSDefaultTolerations) +} + +func (p *podTolerationsPlugin) getNamespaceTolerationsWhitelist(ns *api.Namespace) ([]api.Toleration, error) { + return extractNSTolerations(ns, NSWLTolerations) +} + +func extractNSTolerations(ns *api.Namespace, key string) ([]api.Toleration, error) { + var v1Tolerations []v1.Toleration + if len(ns.Annotations) > 0 && ns.Annotations[key] != "" { + err := json.Unmarshal([]byte(ns.Annotations[key]), &v1Tolerations) + if err != nil { + return nil, err + } + } + + ts := make([]api.Toleration, len(v1Tolerations)) + for i := range v1Tolerations { + if err := v1.Convert_v1_Toleration_To_api_Toleration(&v1Tolerations[i], &ts[i], nil); err != nil { + return nil, err + } + } + + return ts, nil +} diff --git a/plugin/pkg/admission/podtolerationrestriction/admission_test.go b/plugin/pkg/admission/podtolerationrestriction/admission_test.go new file mode 100644 index 00000000000..5fd47146a46 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/admission_test.go @@ -0,0 +1,200 @@ +/* +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 podtolerationrestriction + +import ( + "encoding/json" + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apiserver/pkg/admission" + "k8s.io/kubernetes/pkg/api" + clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" + informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" + kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" + "k8s.io/kubernetes/pkg/util/tolerations" + pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction" +) + +// TestPodAdmission verifies various scenarios involving pod/namespace tolerations +func TestPodAdmission(t *testing.T) { + namespace := &api.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testNamespace", + Namespace: "", + }, + } + + mockClient := &fake.Clientset{} + handler, informerFactory, err := newHandlerForTest(mockClient) + if err != nil { + t.Errorf("unexpected error initializing handler: %v", err) + } + stopCh := make(chan struct{}) + defer close(stopCh) + informerFactory.Start(stopCh) + + pod := &api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "testPod", Namespace: "testNamespace"}, + } + + tests := []struct { + defaultClusterTolerations []api.Toleration + namespaceTolerations []api.Toleration + whitelist []api.Toleration + clusterWhitelist []api.Toleration + podTolerations []api.Toleration + mergedTolerations []api.Toleration + admit bool + testName string + }{ + { + defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + namespaceTolerations: []api.Toleration{}, + podTolerations: []api.Toleration{}, + mergedTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + admit: true, + testName: "default cluster tolerations with empty pod tolerations", + }, + { + defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + namespaceTolerations: []api.Toleration{}, + podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + mergedTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + admit: true, + testName: "default cluster tolerations with pod tolerations specified", + }, + { + defaultClusterTolerations: []api.Toleration{}, + namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + mergedTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + admit: true, + testName: "namespace tolerations", + }, + { + defaultClusterTolerations: []api.Toleration{}, + namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + podTolerations: []api.Toleration{}, + mergedTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + admit: true, + testName: "no pod tolerations", + }, + { + defaultClusterTolerations: []api.Toleration{}, + namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}}, + admit: false, + testName: "conflicting pod and namespace tolerations", + }, + { + defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue2", Effect: "NoSchedule", TolerationSeconds: nil}}, + namespaceTolerations: []api.Toleration{}, + podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}}, + admit: false, + testName: "conflicting pod and default cluster tolerations", + }, + { + defaultClusterTolerations: []api.Toleration{}, + namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + whitelist: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + podTolerations: []api.Toleration{}, + mergedTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + admit: true, + testName: "merged pod tolerations satisfy whitelist", + }, + { + defaultClusterTolerations: []api.Toleration{}, + namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}}, + whitelist: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}}, + podTolerations: []api.Toleration{}, + admit: false, + testName: "merged pod tolerations conflict with the whitelist", + }, + } + for _, test := range tests { + if len(test.namespaceTolerations) > 0 { + tolerationStr, err := json.Marshal(test.namespaceTolerations) + if err != nil { + t.Errorf("error in marshalling namespace tolerations %v", test.namespaceTolerations) + } + namespace.Annotations = map[string]string{NSDefaultTolerations: string(tolerationStr)} + } + + if len(test.whitelist) > 0 { + tolerationStr, err := json.Marshal(test.whitelist) + if err != nil { + t.Errorf("error in marshalling namespace whitelist %v", test.whitelist) + } + namespace.Annotations[NSWLTolerations] = string(tolerationStr) + } + + informerFactory.Core().InternalVersion().Namespaces().Informer().GetStore().Update(namespace) + + handler.pluginConfig = &pluginapi.Configuration{Default: test.defaultClusterTolerations, Whitelist: test.clusterWhitelist} + pod.Spec.Tolerations = test.podTolerations + + err := handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) + if test.admit && err != nil { + t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) + } else if !test.admit && err == nil { + t.Errorf("Test: %s, expected an error", test.testName) + } + + updatedPodTolerations := pod.Spec.Tolerations + if test.admit && !tolerations.EqualTolerations(updatedPodTolerations, test.mergedTolerations) { + t.Errorf("Test: %s, expected: %#v but got: %#v", test.testName, test.mergedTolerations, updatedPodTolerations) + } + } +} + +func TestHandles(t *testing.T) { + for op, shouldHandle := range map[admission.Operation]bool{ + admission.Create: true, + admission.Update: true, + admission.Connect: false, + admission.Delete: false, + } { + + pluginConfig, err := loadConfiguration(nil) + // must not fail + if err != nil { + t.Errorf("%v: error reading default configuration", op) + } + ptPlugin := NewPodTolerationsPlugin(pluginConfig) + if e, a := shouldHandle, ptPlugin.Handles(op); e != a { + t.Errorf("%v: shouldHandle=%t, handles=%t", op, e, a) + } + } +} + +// newHandlerForTest returns the admission controller configured for testing. +func newHandlerForTest(c clientset.Interface) (*podTolerationsPlugin, informers.SharedInformerFactory, error) { + f := informers.NewSharedInformerFactory(c, 5*time.Minute) + pluginConfig, err := loadConfiguration(nil) + // must not fail + if err != nil { + return nil, nil, err + } + handler := NewPodTolerationsPlugin(pluginConfig) + pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil) + pluginInitializer.Initialize(handler) + err = admission.Validate(handler) + return handler, f, err +} diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/OWNERS b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/OWNERS new file mode 100644 index 00000000000..2563b9f7668 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/OWNERS @@ -0,0 +1,2 @@ +reviewers: +approvers: diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/doc.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/doc.go new file mode 100644 index 00000000000..093d630a723 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/doc.go @@ -0,0 +1,19 @@ +/* +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. +*/ + +// +k8s:deepcopy-gen=package,register + +package podtolerationrestriction // import "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction" diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/install.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/install.go new file mode 100644 index 00000000000..5af1c72e7ec --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/install.go @@ -0,0 +1,44 @@ +/* +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 install installs the experimental API group, making it available as +// an option to all of the API encoding/decoding machinery. +package install + +import ( + "k8s.io/apimachinery/pkg/apimachinery/announced" + "k8s.io/apimachinery/pkg/apimachinery/registered" + "k8s.io/apimachinery/pkg/runtime" + internalapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction" + versionedapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1" +) + +// Install registers the API group and adds types to a scheme +func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { + if err := announced.NewGroupMetaFactory( + &announced.GroupMetaFactoryArgs{ + GroupName: internalapi.GroupName, + VersionPreferenceOrder: []string{versionedapi.SchemeGroupVersion.Version}, + ImportPrefix: "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction", + AddInternalObjectsToScheme: internalapi.AddToScheme, + }, + announced.VersionToSchemeFunc{ + versionedapi.SchemeGroupVersion.Version: versionedapi.AddToScheme, + }, + ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { + panic(err) + } +} diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/register.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/register.go new file mode 100644 index 00000000000..8f85e761ee9 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/register.go @@ -0,0 +1,52 @@ +/* +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 podtolerationrestriction + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "podtolerationrestriction.admission.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Kind takes an unqualified kind and returns a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Configuration{}, + ) + return nil +} + +func (obj *Configuration) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta } diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/types.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/types.go new file mode 100644 index 00000000000..b066171a5ed --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/types.go @@ -0,0 +1,33 @@ +/* +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 podtolerationrestriction + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/api" +) + +// Configuration provides configuration for the PodTolerationRestriction admission controller. +type Configuration struct { + metav1.TypeMeta + + // cluster level default tolerations + Default []api.Toleration + + // cluster level whitelist of tolerations + Whitelist []api.Toleration +} diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/defaults.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/defaults.go new file mode 100644 index 00000000000..c4c5a0e9b7b --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/defaults.go @@ -0,0 +1,28 @@ +/* +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 v1alpha1 + +import "k8s.io/apimachinery/pkg/runtime" + +func addDefaultingFuncs(scheme *runtime.Scheme) error { + RegisterDefaults(scheme) + return scheme.AddDefaultingFuncs( + SetDefaults_Configuration, + ) +} + +func SetDefaults_Configuration(obj *Configuration) {} diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/doc.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/doc.go new file mode 100644 index 00000000000..3640b251c3f --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/doc.go @@ -0,0 +1,23 @@ +/* +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. +*/ + +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction +// +k8s:defaulter-gen=TypeMeta + +// Package v1alpha1 is the v1alpha1 version of the API. +// +groupName=podtolerationrestriction.admission.k8s.io +package v1alpha1 // import "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1" diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/register.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/register.go new file mode 100644 index 00000000000..b1ace17ed3a --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/register.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 v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "podtolerationrestriction.admission.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addDefaultingFuncs) + AddToScheme = SchemeBuilder.AddToScheme +) + +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Configuration{}, + ) + return nil +} + +func (obj *Configuration) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta } diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/types.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/types.go new file mode 100644 index 00000000000..147d5d3ac6f --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/types.go @@ -0,0 +1,33 @@ +/* +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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/api/v1" +) + +// Configuration provides configuration for the PodTolerationRestriction admission controller. +type Configuration struct { + metav1.TypeMeta `json:",inline"` + + // cluster level default tolerations + Default []v1.Toleration `json:"default,omitempty"` + + // cluster level whitelist of tolerations + Whitelist []v1.Toleration `json:"whitelist,omitempty"` +} diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation/validation.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation/validation.go new file mode 100644 index 00000000000..6312ed12e31 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation/validation.go @@ -0,0 +1,37 @@ +/* +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 validation + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/kubernetes/pkg/api/validation" + internalapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction" +) + +// ValidateConfiguration validates the configuration. +func ValidateConfiguration(config *internalapi.Configuration) error { + allErrs := field.ErrorList{} + fldpath := field.NewPath("podtolerationrestriction") + allErrs = append(allErrs, validation.ValidateTolerations(config.Default, fldpath.Child("default"))...) + allErrs = append(allErrs, validation.ValidateTolerations(config.Whitelist, fldpath.Child("whitelist"))...) + if len(allErrs) > 0 { + return fmt.Errorf("invalid config: %v", allErrs) + } + return nil +} diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation/validation_test.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation/validation_test.go new file mode 100644 index 00000000000..da41e21dcf6 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation/validation_test.go @@ -0,0 +1,74 @@ +/* +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 validation + +import ( + "testing" + + "k8s.io/kubernetes/pkg/api" + internalapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction" +) + +func TestValidateConfiguration(t *testing.T) { + + tests := []struct { + config internalapi.Configuration + testName string + testStatus bool + }{ + { + config: internalapi.Configuration{ + Default: []api.Toleration{ + {Key: "foo", Operator: "Exists", Value: "", Effect: "NoExecute", TolerationSeconds: &[]int64{60}[0]}, + {Key: "foo", Operator: "Equal", Value: "bar", Effect: "NoExecute", TolerationSeconds: &[]int64{60}[0]}, + {Key: "foo", Operator: "Equal", Value: "bar", Effect: "NoSchedule"}, + {Operator: "Exists", Effect: "NoSchedule"}, + }, + Whitelist: []api.Toleration{ + {Key: "foo", Value: "bar", Effect: "NoSchedule"}, + {Key: "foo", Operator: "Equal", Value: "bar"}, + }, + }, + testName: "Valid cases", + testStatus: true, + }, + { + config: internalapi.Configuration{ + Whitelist: []api.Toleration{{Key: "foo", Operator: "Exists", Value: "bar", Effect: "NoSchedule"}}, + }, + testName: "Invalid case", + testStatus: false, + }, + { + config: internalapi.Configuration{ + Default: []api.Toleration{{Operator: "Equal", Value: "bar", Effect: "NoSchedule"}}, + }, + testName: "Invalid case", + testStatus: false, + }, + } + + for i := range tests { + errs := ValidateConfiguration(&tests[i].config) + if tests[i].testStatus && errs != nil { + t.Errorf("Test: %s, expected success: %v", tests[i].testName, errs) + } + if !tests[i].testStatus && errs == nil { + t.Errorf("Test: %s, expected errors: %v", tests[i].testName, errs) + } + } +} diff --git a/plugin/pkg/admission/podtolerationrestriction/config.go b/plugin/pkg/admission/podtolerationrestriction/config.go new file mode 100644 index 00000000000..49bcd070ba5 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/config.go @@ -0,0 +1,78 @@ +/* +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 podtolerationrestriction + +import ( + "fmt" + "io" + "io/ioutil" + "os" + + "k8s.io/apimachinery/pkg/apimachinery/announced" + "k8s.io/apimachinery/pkg/apimachinery/registered" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + internalapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction" + "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install" + versionedapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1" + "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation" +) + +var ( + groupFactoryRegistry = make(announced.APIGroupFactoryRegistry) + registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) + scheme = runtime.NewScheme() + codecs = serializer.NewCodecFactory(scheme) +) + +func init() { + install.Install(groupFactoryRegistry, registry, scheme) +} + +// LoadConfiguration loads the provided configuration. +func loadConfiguration(config io.Reader) (*internalapi.Configuration, error) { + // if no config is provided, return a default configuration + if config == nil { + externalConfig := &versionedapi.Configuration{} + scheme.Default(externalConfig) + internalConfig := &internalapi.Configuration{} + if err := scheme.Convert(externalConfig, internalConfig, nil); err != nil { + return nil, err + } + return internalConfig, nil + } + // we have a config so parse it. + data, err := ioutil.ReadAll(config) + if err != nil { + return nil, err + } + decoder := codecs.UniversalDecoder() + decodedObj, err := runtime.Decode(decoder, data) + if err != nil { + return nil, err + } + externalConfig, ok := decodedObj.(*internalapi.Configuration) + if !ok { + return nil, fmt.Errorf("unexpected type: %T", decodedObj) + } + + if err := validation.ValidateConfiguration(externalConfig); err != nil { + return nil, err + } + + return externalConfig, nil +} From 0a9cdbb587af0603911e48538a825ff77d650fc7 Mon Sep 17 00:00:00 2001 From: Avesh Agarwal Date: Mon, 27 Feb 2017 13:30:43 -0500 Subject: [PATCH 2/3] Auto-generated stuff. --- cmd/kube-apiserver/app/BUILD | 1 + pkg/util/BUILD | 1 + pkg/util/tolerations/BUILD | 40 ++++++++++ plugin/BUILD | 1 + .../admission/podtolerationrestriction/BUILD | 73 +++++++++++++++++++ .../apis/podtolerationrestriction/BUILD | 44 +++++++++++ .../podtolerationrestriction/install/BUILD | 34 +++++++++ .../podtolerationrestriction/v1alpha1/BUILD | 44 +++++++++++ .../v1alpha1/zz_generated.conversion.go | 63 ++++++++++++++++ .../v1alpha1/zz_generated.deepcopy.go | 67 +++++++++++++++++ .../v1alpha1/zz_generated.defaults.go | 37 ++++++++++ .../podtolerationrestriction/validation/BUILD | 44 +++++++++++ .../zz_generated.deepcopy.go | 67 +++++++++++++++++ 13 files changed, 516 insertions(+) create mode 100644 pkg/util/tolerations/BUILD create mode 100644 plugin/pkg/admission/podtolerationrestriction/BUILD create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/BUILD create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/BUILD create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/BUILD create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.conversion.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.deepcopy.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.defaults.go create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation/BUILD create mode 100644 plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/zz_generated.deepcopy.go diff --git a/cmd/kube-apiserver/app/BUILD b/cmd/kube-apiserver/app/BUILD index fda7aadc899..e025eb35703 100644 --- a/cmd/kube-apiserver/app/BUILD +++ b/cmd/kube-apiserver/app/BUILD @@ -57,6 +57,7 @@ go_library( "//plugin/pkg/admission/persistentvolume/label:go_default_library", "//plugin/pkg/admission/podnodeselector:go_default_library", "//plugin/pkg/admission/podpreset:go_default_library", + "//plugin/pkg/admission/podtolerationrestriction:go_default_library", "//plugin/pkg/admission/resourcequota:go_default_library", "//plugin/pkg/admission/security/podsecuritypolicy:go_default_library", "//plugin/pkg/admission/securitycontext/scdeny:go_default_library", diff --git a/pkg/util/BUILD b/pkg/util/BUILD index 1725eea188d..b5885d18cdd 100644 --- a/pkg/util/BUILD +++ b/pkg/util/BUILD @@ -96,6 +96,7 @@ filegroup( "//pkg/util/taints:all-srcs", "//pkg/util/term:all-srcs", "//pkg/util/threading:all-srcs", + "//pkg/util/tolerations:all-srcs", "//pkg/util/uuid:all-srcs", "//pkg/util/validation:all-srcs", "//pkg/util/version:all-srcs", diff --git a/pkg/util/tolerations/BUILD b/pkg/util/tolerations/BUILD new file mode 100644 index 00000000000..95fa6fd3255 --- /dev/null +++ b/pkg/util/tolerations/BUILD @@ -0,0 +1,40 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "tolerations.go", + ], + tags = ["automanaged"], + deps = ["//pkg/api:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) + +go_test( + name = "go_default_test", + srcs = ["tolerations_test.go"], + library = ":go_default_library", + tags = ["automanaged"], + deps = ["//pkg/api:go_default_library"], +) diff --git a/plugin/BUILD b/plugin/BUILD index 41840c11cc9..cf8c9c5be76 100644 --- a/plugin/BUILD +++ b/plugin/BUILD @@ -30,6 +30,7 @@ filegroup( "//plugin/pkg/admission/persistentvolume/label:all-srcs", "//plugin/pkg/admission/podnodeselector:all-srcs", "//plugin/pkg/admission/podpreset:all-srcs", + "//plugin/pkg/admission/podtolerationrestriction:all-srcs", "//plugin/pkg/admission/resourcequota:all-srcs", "//plugin/pkg/admission/security:all-srcs", "//plugin/pkg/admission/securitycontext/scdeny:all-srcs", diff --git a/plugin/pkg/admission/podtolerationrestriction/BUILD b/plugin/pkg/admission/podtolerationrestriction/BUILD new file mode 100644 index 00000000000..a2e0dc4f715 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/BUILD @@ -0,0 +1,73 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_test( + name = "go_default_test", + srcs = ["admission_test.go"], + library = ":go_default_library", + tags = ["automanaged"], + deps = [ + "//pkg/api:go_default_library", + "//pkg/client/clientset_generated/internalclientset:go_default_library", + "//pkg/client/clientset_generated/internalclientset/fake:go_default_library", + "//pkg/client/informers/informers_generated/internalversion:go_default_library", + "//pkg/kubeapiserver/admission:go_default_library", + "//pkg/util/tolerations:go_default_library", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", + "//vendor:k8s.io/apiserver/pkg/admission", + ], +) + +go_library( + name = "go_default_library", + srcs = [ + "admission.go", + "config.go", + ], + tags = ["automanaged"], + deps = [ + "//pkg/api:go_default_library", + "//pkg/api/v1:go_default_library", + "//pkg/client/clientset_generated/internalclientset:go_default_library", + "//pkg/client/informers/informers_generated/internalversion:go_default_library", + "//pkg/client/listers/core/internalversion:go_default_library", + "//pkg/kubeapiserver/admission:go_default_library", + "//pkg/util/tolerations:go_default_library", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install:go_default_library", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1:go_default_library", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation:go_default_library", + "//vendor:github.com/golang/glog", + "//vendor:k8s.io/apimachinery/pkg/api/errors", + "//vendor:k8s.io/apimachinery/pkg/apimachinery/announced", + "//vendor:k8s.io/apimachinery/pkg/apimachinery/registered", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", + "//vendor:k8s.io/apimachinery/pkg/runtime", + "//vendor:k8s.io/apimachinery/pkg/runtime/serializer", + "//vendor:k8s.io/apiserver/pkg/admission", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/BUILD b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/BUILD new file mode 100644 index 00000000000..0a4514c984b --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/BUILD @@ -0,0 +1,44 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "register.go", + "types.go", + "zz_generated.deepcopy.go", + ], + tags = ["automanaged"], + deps = [ + "//pkg/api:go_default_library", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", + "//vendor:k8s.io/apimachinery/pkg/conversion", + "//vendor:k8s.io/apimachinery/pkg/runtime", + "//vendor:k8s.io/apimachinery/pkg/runtime/schema", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install:all-srcs", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1:all-srcs", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/BUILD b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/BUILD new file mode 100644 index 00000000000..e23bdd255b4 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/BUILD @@ -0,0 +1,34 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = ["install.go"], + tags = ["automanaged"], + deps = [ + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1:go_default_library", + "//vendor:k8s.io/apimachinery/pkg/apimachinery/announced", + "//vendor:k8s.io/apimachinery/pkg/apimachinery/registered", + "//vendor:k8s.io/apimachinery/pkg/runtime", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/BUILD b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/BUILD new file mode 100644 index 00000000000..10fcb5c0d88 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/BUILD @@ -0,0 +1,44 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "defaults.go", + "doc.go", + "register.go", + "types.go", + "zz_generated.conversion.go", + "zz_generated.deepcopy.go", + "zz_generated.defaults.go", + ], + tags = ["automanaged"], + deps = [ + "//pkg/api:go_default_library", + "//pkg/api/v1:go_default_library", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", + "//vendor:k8s.io/apimachinery/pkg/conversion", + "//vendor:k8s.io/apimachinery/pkg/runtime", + "//vendor:k8s.io/apimachinery/pkg/runtime/schema", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.conversion.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.conversion.go new file mode 100644 index 00000000000..e7e7f135967 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.conversion.go @@ -0,0 +1,63 @@ +// +build !ignore_autogenerated + +/* +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. +*/ + +// This file was autogenerated by conversion-gen. Do not edit it manually! + +package v1alpha1 + +import ( + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + api "k8s.io/kubernetes/pkg/api" + v1 "k8s.io/kubernetes/pkg/api/v1" + podtolerationrestriction "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction" + unsafe "unsafe" +) + +func init() { + SchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(scheme *runtime.Scheme) error { + return scheme.AddGeneratedConversionFuncs( + Convert_v1alpha1_Configuration_To_podtolerationrestriction_Configuration, + Convert_podtolerationrestriction_Configuration_To_v1alpha1_Configuration, + ) +} + +func autoConvert_v1alpha1_Configuration_To_podtolerationrestriction_Configuration(in *Configuration, out *podtolerationrestriction.Configuration, s conversion.Scope) error { + out.Default = *(*[]api.Toleration)(unsafe.Pointer(&in.Default)) + out.Whitelist = *(*[]api.Toleration)(unsafe.Pointer(&in.Whitelist)) + return nil +} + +func Convert_v1alpha1_Configuration_To_podtolerationrestriction_Configuration(in *Configuration, out *podtolerationrestriction.Configuration, s conversion.Scope) error { + return autoConvert_v1alpha1_Configuration_To_podtolerationrestriction_Configuration(in, out, s) +} + +func autoConvert_podtolerationrestriction_Configuration_To_v1alpha1_Configuration(in *podtolerationrestriction.Configuration, out *Configuration, s conversion.Scope) error { + out.Default = *(*[]v1.Toleration)(unsafe.Pointer(&in.Default)) + out.Whitelist = *(*[]v1.Toleration)(unsafe.Pointer(&in.Whitelist)) + return nil +} + +func Convert_podtolerationrestriction_Configuration_To_v1alpha1_Configuration(in *podtolerationrestriction.Configuration, out *Configuration, s conversion.Scope) error { + return autoConvert_podtolerationrestriction_Configuration_To_v1alpha1_Configuration(in, out, s) +} diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.deepcopy.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..9dd38a31695 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,67 @@ +// +build !ignore_autogenerated + +/* +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. +*/ + +// This file was autogenerated by deepcopy-gen. Do not edit it manually! + +package v1alpha1 + +import ( + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + v1 "k8s.io/kubernetes/pkg/api/v1" + reflect "reflect" +) + +func init() { + SchemeBuilder.Register(RegisterDeepCopies) +} + +// RegisterDeepCopies adds deep-copy functions to the given scheme. Public +// to allow building arbitrary schemes. +func RegisterDeepCopies(scheme *runtime.Scheme) error { + return scheme.AddGeneratedDeepCopyFuncs( + conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_Configuration, InType: reflect.TypeOf(&Configuration{})}, + ) +} + +func DeepCopy_v1alpha1_Configuration(in interface{}, out interface{}, c *conversion.Cloner) error { + { + in := in.(*Configuration) + out := out.(*Configuration) + *out = *in + if in.Default != nil { + in, out := &in.Default, &out.Default + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + if err := v1.DeepCopy_v1_Toleration(&(*in)[i], &(*out)[i], c); err != nil { + return err + } + } + } + if in.Whitelist != nil { + in, out := &in.Whitelist, &out.Whitelist + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + if err := v1.DeepCopy_v1_Toleration(&(*in)[i], &(*out)[i], c); err != nil { + return err + } + } + } + return nil + } +} diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.defaults.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.defaults.go new file mode 100644 index 00000000000..53f9cb92ef7 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.defaults.go @@ -0,0 +1,37 @@ +// +build !ignore_autogenerated + +/* +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. +*/ + +// This file was autogenerated by defaulter-gen. Do not edit it manually! + +package v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + scheme.AddTypeDefaultingFunc(&Configuration{}, func(obj interface{}) { SetObjectDefaults_Configuration(obj.(*Configuration)) }) + return nil +} + +func SetObjectDefaults_Configuration(in *Configuration) { + SetDefaults_Configuration(in) +} diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation/BUILD b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation/BUILD new file mode 100644 index 00000000000..7c11b0ce90c --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation/BUILD @@ -0,0 +1,44 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = ["validation.go"], + tags = ["automanaged"], + deps = [ + "//pkg/api/validation:go_default_library", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library", + "//vendor:k8s.io/apimachinery/pkg/util/validation/field", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) + +go_test( + name = "go_default_test", + srcs = ["validation_test.go"], + library = ":go_default_library", + tags = ["automanaged"], + deps = [ + "//pkg/api:go_default_library", + "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library", + ], +) diff --git a/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/zz_generated.deepcopy.go b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/zz_generated.deepcopy.go new file mode 100644 index 00000000000..49d1f043828 --- /dev/null +++ b/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/zz_generated.deepcopy.go @@ -0,0 +1,67 @@ +// +build !ignore_autogenerated + +/* +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. +*/ + +// This file was autogenerated by deepcopy-gen. Do not edit it manually! + +package podtolerationrestriction + +import ( + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + api "k8s.io/kubernetes/pkg/api" + reflect "reflect" +) + +func init() { + SchemeBuilder.Register(RegisterDeepCopies) +} + +// RegisterDeepCopies adds deep-copy functions to the given scheme. Public +// to allow building arbitrary schemes. +func RegisterDeepCopies(scheme *runtime.Scheme) error { + return scheme.AddGeneratedDeepCopyFuncs( + conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_podtolerationrestriction_Configuration, InType: reflect.TypeOf(&Configuration{})}, + ) +} + +func DeepCopy_podtolerationrestriction_Configuration(in interface{}, out interface{}, c *conversion.Cloner) error { + { + in := in.(*Configuration) + out := out.(*Configuration) + *out = *in + if in.Default != nil { + in, out := &in.Default, &out.Default + *out = make([]api.Toleration, len(*in)) + for i := range *in { + if err := api.DeepCopy_api_Toleration(&(*in)[i], &(*out)[i], c); err != nil { + return err + } + } + } + if in.Whitelist != nil { + in, out := &in.Whitelist, &out.Whitelist + *out = make([]api.Toleration, len(*in)) + for i := range *in { + if err := api.DeepCopy_api_Toleration(&(*in)[i], &(*out)[i], c); err != nil { + return err + } + } + } + return nil + } +} From 5f309eec9ac079866444dc7c8d40ab26dd6bbf56 Mon Sep 17 00:00:00 2001 From: Avesh Agarwal Date: Mon, 27 Feb 2017 13:31:02 -0500 Subject: [PATCH 3/3] Fix golint. --- hack/.linted_packages | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hack/.linted_packages b/hack/.linted_packages index 7d7e85a0202..21623d40b87 100644 --- a/hack/.linted_packages +++ b/hack/.linted_packages @@ -279,6 +279,8 @@ plugin/pkg/admission/gc plugin/pkg/admission/imagepolicy plugin/pkg/admission/namespace/autoprovision plugin/pkg/admission/namespace/exists +plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install +plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation plugin/pkg/admission/resourcequota/apis/resourcequota/install plugin/pkg/admission/resourcequota/apis/resourcequota/validation plugin/pkg/admission/securitycontext/scdeny