Allow pods to opt out of PodPreset mutation
An annotation in the pod spec of the form: podpreset.admission.kubernetes.io/exclude: "true" Will cause the admission controller to skip manipulating the pod spec, no matter the labelling. The annotation for a podpreset acting on a pod has also been slightly modified to contain a podpreset prefix: podpreset.admission.kubernetes.io/podpreset-{name} = resource version Fixes #44161
This commit is contained in:
@@ -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
|
||||
|
@@ -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()
|
||||
|
Reference in New Issue
Block a user