diff --git a/pkg/api/annotation_key_constants.go b/pkg/api/annotation_key_constants.go index 55bf20f9a0c..e1080a34a22 100644 --- a/pkg/api/annotation_key_constants.go +++ b/pkg/api/annotation_key_constants.go @@ -23,6 +23,9 @@ const ( // webhook backend fails. ImagePolicyFailedOpenKey string = "alpha.image-policy.k8s.io/failed-open" + // PodPresetOptOutAnnotationKey represents the annotation key for a pod to exempt itself from pod preset manipulation + PodPresetOptOutAnnotationKey string = "podpreset.admission.kubernetes.io/exclude" + // MirrorAnnotationKey represents the annotation key set by kubelets when creating mirror pods MirrorPodAnnotationKey string = "kubernetes.io/config.mirror" diff --git a/pkg/api/v1/annotation_key_constants.go b/pkg/api/v1/annotation_key_constants.go index 8591f08b4b5..bb4588554ab 100644 --- a/pkg/api/v1/annotation_key_constants.go +++ b/pkg/api/v1/annotation_key_constants.go @@ -23,6 +23,9 @@ const ( // webhook backend fails. ImagePolicyFailedOpenKey string = "alpha.image-policy.k8s.io/failed-open" + // PodPresetOptOutAnnotationKey represents the annotation key for a pod to exempt itself from pod preset manipulation + PodPresetOptOutAnnotationKey string = "podpreset.admission.kubernetes.io/exclude" + // MirrorAnnotationKey represents the annotation key set by kubelets when creating mirror pods MirrorPodAnnotationKey string = "kubernetes.io/config.mirror" diff --git a/plugin/pkg/admission/podpreset/admission.go b/plugin/pkg/admission/podpreset/admission.go index 972a91f1814..4ee7e8be73a 100644 --- a/plugin/pkg/admission/podpreset/admission.go +++ b/plugin/pkg/admission/podpreset/admission.go @@ -104,6 +104,14 @@ func (c *podPresetPlugin) Admit(a admission.Attributes) error { } list, err := c.lister.PodPresets(pod.GetNamespace()).List(labels.Everything()) + + // Ignore if exclusion annotation is present + if podAnnotations := pod.GetAnnotations(); podAnnotations != nil { + glog.V(5).Infof("Looking at pod annotations, found: %v", podAnnotations) + if podAnnotations[api.PodPresetOptOutAnnotationKey] == "true" { + return nil + } + } if err != nil { return fmt.Errorf("listing pod presets failed: %v", err) } @@ -182,7 +190,8 @@ func (c *podPresetPlugin) Admit(a admission.Attributes) error { if pod.ObjectMeta.Annotations == nil { pod.ObjectMeta.Annotations = map[string]string{} } - pod.ObjectMeta.Annotations[fmt.Sprintf("%s/%s", annotationPrefix, pip.GetName())] = pip.GetResourceVersion() + + pod.ObjectMeta.Annotations[fmt.Sprintf("%s/podpreset-%s", annotationPrefix, pip.GetName())] = pip.GetResourceVersion() } return nil diff --git a/plugin/pkg/admission/podpreset/admission_test.go b/plugin/pkg/admission/podpreset/admission_test.go index 7cfd5c17101..4409bd46224 100644 --- a/plugin/pkg/admission/podpreset/admission_test.go +++ b/plugin/pkg/admission/podpreset/admission_test.go @@ -623,6 +623,78 @@ func TestAdmitMirrorPod(t *testing.T) { } } +func TestExclusionNoAdmit(t *testing.T) { + containerName := "container" + + pod := &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mypod", + Namespace: "namespace", + Labels: map[string]string{ + "security": "S2", + }, + Annotations: map[string]string{ + api.PodPresetOptOutAnnotationKey: "true", + }, + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: containerName, + Env: []api.EnvVar{{Name: "abc", Value: "value2"}, {Name: "ABCD", Value: "value3"}}, + }, + }, + }, + } + + pip := &settings.PodPreset{ + ObjectMeta: v1.ObjectMeta{ + Name: "hello", + Namespace: "namespace", + }, + Spec: settings.PodPresetSpec{ + Selector: v1.LabelSelector{ + MatchExpressions: []v1.LabelSelectorRequirement{ + { + Key: "security", + Operator: v1.LabelSelectorOpIn, + Values: []string{"S2"}, + }, + }, + }, + Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}}, + Env: []api.EnvVar{{Name: "abcd", Value: "value"}, {Name: "ABC", Value: "value"}}, + EnvFrom: []api.EnvFromSource{ + { + ConfigMapRef: &api.ConfigMapEnvSource{ + LocalObjectReference: api.LocalObjectReference{Name: "abc"}, + }, + }, + { + Prefix: "pre_", + ConfigMapRef: &api.ConfigMapEnvSource{ + LocalObjectReference: api.LocalObjectReference{Name: "abc"}, + }, + }, + }, + }, + } + originalPod, err := api.Scheme.Copy(pod) + if err != nil { + t.Fatal(err) + } + + err = admitPod(pod, pip) + if err != nil { + t.Fatal(err) + } + + // verify PodSpec has not been mutated + if !reflect.DeepEqual(pod, originalPod) { + t.Fatalf("Expected pod spec of '%v' to be unchanged", pod.Name) + } +} + func admitPod(pod *api.Pod, pip *settings.PodPreset) error { informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc()) store := informerFactory.Settings().InternalVersion().PodPresets().Informer().GetStore() diff --git a/staging/src/k8s.io/client-go/pkg/api/annotation_key_constants.go b/staging/src/k8s.io/client-go/pkg/api/annotation_key_constants.go index 55bf20f9a0c..e1080a34a22 100644 --- a/staging/src/k8s.io/client-go/pkg/api/annotation_key_constants.go +++ b/staging/src/k8s.io/client-go/pkg/api/annotation_key_constants.go @@ -23,6 +23,9 @@ const ( // webhook backend fails. ImagePolicyFailedOpenKey string = "alpha.image-policy.k8s.io/failed-open" + // PodPresetOptOutAnnotationKey represents the annotation key for a pod to exempt itself from pod preset manipulation + PodPresetOptOutAnnotationKey string = "podpreset.admission.kubernetes.io/exclude" + // MirrorAnnotationKey represents the annotation key set by kubelets when creating mirror pods MirrorPodAnnotationKey string = "kubernetes.io/config.mirror" diff --git a/staging/src/k8s.io/client-go/pkg/api/v1/annotation_key_constants.go b/staging/src/k8s.io/client-go/pkg/api/v1/annotation_key_constants.go index 8591f08b4b5..bb4588554ab 100644 --- a/staging/src/k8s.io/client-go/pkg/api/v1/annotation_key_constants.go +++ b/staging/src/k8s.io/client-go/pkg/api/v1/annotation_key_constants.go @@ -23,6 +23,9 @@ const ( // webhook backend fails. ImagePolicyFailedOpenKey string = "alpha.image-policy.k8s.io/failed-open" + // PodPresetOptOutAnnotationKey represents the annotation key for a pod to exempt itself from pod preset manipulation + PodPresetOptOutAnnotationKey string = "podpreset.admission.kubernetes.io/exclude" + // MirrorAnnotationKey represents the annotation key set by kubelets when creating mirror pods MirrorPodAnnotationKey string = "kubernetes.io/config.mirror" diff --git a/test/e2e/podpreset.go b/test/e2e/podpreset.go index 5cd75703460..4a7c82cab88 100644 --- a/test/e2e/podpreset.go +++ b/test/e2e/podpreset.go @@ -140,7 +140,7 @@ var _ = framework.KubeDescribe("PodPreset", func() { Expect(err).NotTo(HaveOccurred(), "failed to GET scheduled pod") // check the annotation is there - if _, ok := pod.Annotations["podpreset.admission.kubernetes.io/hello"]; !ok { + if _, ok := pod.Annotations["podpreset.admission.kubernetes.io/podpreset-hello"]; !ok { framework.Failf("Annotation not found in pod annotations: \n%v\n", pod.Annotations) } @@ -246,7 +246,7 @@ var _ = framework.KubeDescribe("PodPreset", func() { Expect(err).NotTo(HaveOccurred(), "failed to GET scheduled pod") // check the annotation is not there - if _, ok := pod.Annotations["podpreset.admission.kubernetes.io/hello"]; ok { + if _, ok := pod.Annotations["podpreset.admission.kubernetes.io/podpreset-hello"]; ok { framework.Failf("Annotation found in pod annotations and should not be: \n%v\n", pod.Annotations) }