Merge pull request #81032 from liggitt/isolate-webhook-e2e
Scope e2e webhooks to avoid cross-test interference
This commit is contained in:
		@@ -59,20 +59,6 @@ const (
 | 
				
			|||||||
	servicePort     = 8443
 | 
						servicePort     = 8443
 | 
				
			||||||
	roleBindingName = "webhook-auth-reader"
 | 
						roleBindingName = "webhook-auth-reader"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The webhook configuration names should not be reused between test instances.
 | 
					 | 
				
			||||||
	crWebhookConfigName                    = "e2e-test-webhook-config-cr"
 | 
					 | 
				
			||||||
	webhookConfigName                      = "e2e-test-webhook-config"
 | 
					 | 
				
			||||||
	attachingPodWebhookConfigName          = "e2e-test-webhook-config-attaching-pod"
 | 
					 | 
				
			||||||
	mutatingWebhookConfigName              = "e2e-test-mutating-webhook-config"
 | 
					 | 
				
			||||||
	podMutatingWebhookConfigName           = "e2e-test-mutating-webhook-pod"
 | 
					 | 
				
			||||||
	webhookFailClosedConfigName            = "e2e-test-webhook-fail-closed"
 | 
					 | 
				
			||||||
	validatingWebhookForWebhooksConfigName = "e2e-test-validating-webhook-for-webhooks-config"
 | 
					 | 
				
			||||||
	mutatingWebhookForWebhooksConfigName   = "e2e-test-mutating-webhook-for-webhooks-config"
 | 
					 | 
				
			||||||
	dummyValidatingWebhookConfigName       = "e2e-test-dummy-validating-webhook-config"
 | 
					 | 
				
			||||||
	dummyMutatingWebhookConfigName         = "e2e-test-dummy-mutating-webhook-config"
 | 
					 | 
				
			||||||
	crdWebhookConfigName                   = "e2e-test-webhook-config-crd"
 | 
					 | 
				
			||||||
	slowWebhookConfigName                  = "e2e-test-webhook-config-slow"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	skipNamespaceLabelKey     = "skip-webhook-admission"
 | 
						skipNamespaceLabelKey     = "skip-webhook-admission"
 | 
				
			||||||
	skipNamespaceLabelValue   = "yes"
 | 
						skipNamespaceLabelValue   = "yes"
 | 
				
			||||||
	skippedNamespaceName      = "exempted-namesapce"
 | 
						skippedNamespaceName      = "exempted-namesapce"
 | 
				
			||||||
@@ -111,13 +97,13 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
 | 
				
			|||||||
			framework.Skipf("dynamic configuration of webhooks requires the admissionregistration.k8s.io group to be enabled")
 | 
								framework.Skipf("dynamic configuration of webhooks requires the admissionregistration.k8s.io group to be enabled")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Make sure the namespace created for the test is labeled to be selected by the webhooks
 | 
				
			||||||
 | 
							labelNamespace(f, f.Namespace.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ginkgo.By("Setting up server cert")
 | 
							ginkgo.By("Setting up server cert")
 | 
				
			||||||
		context = setupServerCert(namespaceName, serviceName)
 | 
							context = setupServerCert(namespaceName, serviceName)
 | 
				
			||||||
		createAuthReaderRoleBinding(f, namespaceName)
 | 
							createAuthReaderRoleBinding(f, namespaceName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Note that in 1.9 we will have backwards incompatible change to
 | 
					 | 
				
			||||||
		// admission webhooks, so the image will be updated to 1.9 sometime in
 | 
					 | 
				
			||||||
		// the development 1.9 cycle.
 | 
					 | 
				
			||||||
		deployWebhookAndService(f, imageutils.GetE2EImage(imageutils.Agnhost), context)
 | 
							deployWebhookAndService(f, imageutils.GetE2EImage(imageutils.Agnhost), context)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -126,13 +112,13 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ginkgo.It("Should be able to deny pod and configmap creation", func() {
 | 
						ginkgo.It("Should be able to deny pod and configmap creation", func() {
 | 
				
			||||||
		webhookCleanup := registerWebhook(f, context)
 | 
							webhookCleanup := registerWebhook(f, f.UniqueName, context)
 | 
				
			||||||
		defer webhookCleanup()
 | 
							defer webhookCleanup()
 | 
				
			||||||
		testWebhook(f)
 | 
							testWebhook(f)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ginkgo.It("Should be able to deny attaching pod", func() {
 | 
						ginkgo.It("Should be able to deny attaching pod", func() {
 | 
				
			||||||
		webhookCleanup := registerWebhookForAttachingPod(f, context)
 | 
							webhookCleanup := registerWebhookForAttachingPod(f, f.UniqueName, context)
 | 
				
			||||||
		defer webhookCleanup()
 | 
							defer webhookCleanup()
 | 
				
			||||||
		testAttachingPodWebhook(f)
 | 
							testAttachingPodWebhook(f)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -143,36 +129,36 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		defer testcrd.CleanUp()
 | 
							defer testcrd.CleanUp()
 | 
				
			||||||
		webhookCleanup := registerWebhookForCustomResource(f, context, testcrd)
 | 
							webhookCleanup := registerWebhookForCustomResource(f, f.UniqueName, context, testcrd)
 | 
				
			||||||
		defer webhookCleanup()
 | 
							defer webhookCleanup()
 | 
				
			||||||
		testCustomResourceWebhook(f, testcrd.Crd, testcrd.DynamicClients["v1"])
 | 
							testCustomResourceWebhook(f, testcrd.Crd, testcrd.DynamicClients["v1"])
 | 
				
			||||||
		testBlockingCustomResourceDeletion(f, testcrd.Crd, testcrd.DynamicClients["v1"])
 | 
							testBlockingCustomResourceDeletion(f, testcrd.Crd, testcrd.DynamicClients["v1"])
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ginkgo.It("Should unconditionally reject operations on fail closed webhook", func() {
 | 
						ginkgo.It("Should unconditionally reject operations on fail closed webhook", func() {
 | 
				
			||||||
		webhookCleanup := registerFailClosedWebhook(f, context)
 | 
							webhookCleanup := registerFailClosedWebhook(f, f.UniqueName, context)
 | 
				
			||||||
		defer webhookCleanup()
 | 
							defer webhookCleanup()
 | 
				
			||||||
		testFailClosedWebhook(f)
 | 
							testFailClosedWebhook(f)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ginkgo.It("Should mutate configmap", func() {
 | 
						ginkgo.It("Should mutate configmap", func() {
 | 
				
			||||||
		webhookCleanup := registerMutatingWebhookForConfigMap(f, context)
 | 
							webhookCleanup := registerMutatingWebhookForConfigMap(f, f.UniqueName, context)
 | 
				
			||||||
		defer webhookCleanup()
 | 
							defer webhookCleanup()
 | 
				
			||||||
		testMutatingConfigMapWebhook(f)
 | 
							testMutatingConfigMapWebhook(f)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ginkgo.It("Should mutate pod and apply defaults after mutation", func() {
 | 
						ginkgo.It("Should mutate pod and apply defaults after mutation", func() {
 | 
				
			||||||
		webhookCleanup := registerMutatingWebhookForPod(f, context)
 | 
							webhookCleanup := registerMutatingWebhookForPod(f, f.UniqueName, context)
 | 
				
			||||||
		defer webhookCleanup()
 | 
							defer webhookCleanup()
 | 
				
			||||||
		testMutatingPodWebhook(f)
 | 
							testMutatingPodWebhook(f)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ginkgo.It("Should not be able to mutate or prevent deletion of webhook configuration objects", func() {
 | 
						ginkgo.It("Should not be able to mutate or prevent deletion of webhook configuration objects", func() {
 | 
				
			||||||
		validatingWebhookCleanup := registerValidatingWebhookForWebhookConfigurations(f, context)
 | 
							validatingWebhookCleanup := registerValidatingWebhookForWebhookConfigurations(f, f.UniqueName+"blocking", context)
 | 
				
			||||||
		defer validatingWebhookCleanup()
 | 
							defer validatingWebhookCleanup()
 | 
				
			||||||
		mutatingWebhookCleanup := registerMutatingWebhookForWebhookConfigurations(f, context)
 | 
							mutatingWebhookCleanup := registerMutatingWebhookForWebhookConfigurations(f, f.UniqueName+"blocking", context)
 | 
				
			||||||
		defer mutatingWebhookCleanup()
 | 
							defer mutatingWebhookCleanup()
 | 
				
			||||||
		testWebhooksForWebhookConfigurations(f)
 | 
							testWebhooksForWebhookConfigurations(f, f.UniqueName)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ginkgo.It("Should mutate custom resource", func() {
 | 
						ginkgo.It("Should mutate custom resource", func() {
 | 
				
			||||||
@@ -181,13 +167,13 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		defer testcrd.CleanUp()
 | 
							defer testcrd.CleanUp()
 | 
				
			||||||
		webhookCleanup := registerMutatingWebhookForCustomResource(f, context, testcrd)
 | 
							webhookCleanup := registerMutatingWebhookForCustomResource(f, f.UniqueName, context, testcrd)
 | 
				
			||||||
		defer webhookCleanup()
 | 
							defer webhookCleanup()
 | 
				
			||||||
		testMutatingCustomResourceWebhook(f, testcrd.Crd, testcrd.DynamicClients["v1"], false)
 | 
							testMutatingCustomResourceWebhook(f, testcrd.Crd, testcrd.DynamicClients["v1"], false)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ginkgo.It("Should deny crd creation", func() {
 | 
						ginkgo.It("Should deny crd creation", func() {
 | 
				
			||||||
		crdWebhookCleanup := registerValidatingWebhookForCRD(f, context)
 | 
							crdWebhookCleanup := registerValidatingWebhookForCRD(f, f.UniqueName, context)
 | 
				
			||||||
		defer crdWebhookCleanup()
 | 
							defer crdWebhookCleanup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		testCRDDenyWebhook(f)
 | 
							testCRDDenyWebhook(f)
 | 
				
			||||||
@@ -199,7 +185,7 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		defer testcrd.CleanUp()
 | 
							defer testcrd.CleanUp()
 | 
				
			||||||
		webhookCleanup := registerMutatingWebhookForCustomResource(f, context, testcrd)
 | 
							webhookCleanup := registerMutatingWebhookForCustomResource(f, f.UniqueName, context, testcrd)
 | 
				
			||||||
		defer webhookCleanup()
 | 
							defer webhookCleanup()
 | 
				
			||||||
		testMultiVersionCustomResourceWebhook(f, testcrd)
 | 
							testMultiVersionCustomResourceWebhook(f, testcrd)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -228,7 +214,7 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		defer testcrd.CleanUp()
 | 
							defer testcrd.CleanUp()
 | 
				
			||||||
		webhookCleanup := registerMutatingWebhookForCustomResource(f, context, testcrd)
 | 
							webhookCleanup := registerMutatingWebhookForCustomResource(f, f.UniqueName, context, testcrd)
 | 
				
			||||||
		defer webhookCleanup()
 | 
							defer webhookCleanup()
 | 
				
			||||||
		testMutatingCustomResourceWebhook(f, testcrd.Crd, testcrd.DynamicClients["v1"], prune)
 | 
							testMutatingCustomResourceWebhook(f, testcrd.Crd, testcrd.DynamicClients["v1"], prune)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -238,22 +224,22 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
 | 
				
			|||||||
		policyIgnore := admissionregistrationv1.Ignore
 | 
							policyIgnore := admissionregistrationv1.Ignore
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ginkgo.By("Setting timeout (1s) shorter than webhook latency (5s)")
 | 
							ginkgo.By("Setting timeout (1s) shorter than webhook latency (5s)")
 | 
				
			||||||
		slowWebhookCleanup := registerSlowWebhook(f, context, &policyFail, pointer.Int32Ptr(1))
 | 
							slowWebhookCleanup := registerSlowWebhook(f, f.UniqueName, context, &policyFail, pointer.Int32Ptr(1))
 | 
				
			||||||
		testSlowWebhookTimeoutFailEarly(f)
 | 
							testSlowWebhookTimeoutFailEarly(f)
 | 
				
			||||||
		slowWebhookCleanup()
 | 
							slowWebhookCleanup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ginkgo.By("Having no error when timeout is shorter than webhook latency and failure policy is ignore")
 | 
							ginkgo.By("Having no error when timeout is shorter than webhook latency and failure policy is ignore")
 | 
				
			||||||
		slowWebhookCleanup = registerSlowWebhook(f, context, &policyIgnore, pointer.Int32Ptr(1))
 | 
							slowWebhookCleanup = registerSlowWebhook(f, f.UniqueName, context, &policyIgnore, pointer.Int32Ptr(1))
 | 
				
			||||||
		testSlowWebhookTimeoutNoError(f)
 | 
							testSlowWebhookTimeoutNoError(f)
 | 
				
			||||||
		slowWebhookCleanup()
 | 
							slowWebhookCleanup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ginkgo.By("Having no error when timeout is longer than webhook latency")
 | 
							ginkgo.By("Having no error when timeout is longer than webhook latency")
 | 
				
			||||||
		slowWebhookCleanup = registerSlowWebhook(f, context, &policyFail, pointer.Int32Ptr(10))
 | 
							slowWebhookCleanup = registerSlowWebhook(f, f.UniqueName, context, &policyFail, pointer.Int32Ptr(10))
 | 
				
			||||||
		testSlowWebhookTimeoutNoError(f)
 | 
							testSlowWebhookTimeoutNoError(f)
 | 
				
			||||||
		slowWebhookCleanup()
 | 
							slowWebhookCleanup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ginkgo.By("Having no error when timeout is empty (defaulted to 10s in v1beta1)")
 | 
							ginkgo.By("Having no error when timeout is empty (defaulted to 10s in v1beta1)")
 | 
				
			||||||
		slowWebhookCleanup = registerSlowWebhook(f, context, &policyFail, nil)
 | 
							slowWebhookCleanup = registerSlowWebhook(f, f.UniqueName, context, &policyFail, nil)
 | 
				
			||||||
		testSlowWebhookTimeoutNoError(f)
 | 
							testSlowWebhookTimeoutNoError(f)
 | 
				
			||||||
		slowWebhookCleanup()
 | 
							slowWebhookCleanup()
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -414,19 +400,22 @@ func deployWebhookAndService(f *framework.Framework, image string, context *cert
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func strPtr(s string) *string { return &s }
 | 
					func strPtr(s string) *string { return &s }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func registerWebhook(f *framework.Framework, context *certContext) func() {
 | 
					func registerWebhook(f *framework.Framework, configName string, context *certContext) func() {
 | 
				
			||||||
	client := f.ClientSet
 | 
						client := f.ClientSet
 | 
				
			||||||
	ginkgo.By("Registering the webhook via the AdmissionRegistration API")
 | 
						ginkgo.By("Registering the webhook via the AdmissionRegistration API")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace := f.Namespace.Name
 | 
						namespace := f.Namespace.Name
 | 
				
			||||||
	configName := webhookConfigName
 | 
					 | 
				
			||||||
	// A webhook that cannot talk to server, with fail-open policy
 | 
						// A webhook that cannot talk to server, with fail-open policy
 | 
				
			||||||
	failOpenHook := failingWebhook(namespace, "fail-open.k8s.io")
 | 
						failOpenHook := failingWebhook(namespace, "fail-open.k8s.io")
 | 
				
			||||||
	policyIgnore := admissionregistrationv1.Ignore
 | 
						policyIgnore := admissionregistrationv1.Ignore
 | 
				
			||||||
	failOpenHook.FailurePolicy = &policyIgnore
 | 
						failOpenHook.FailurePolicy = &policyIgnore
 | 
				
			||||||
 | 
						failOpenHook.NamespaceSelector = &metav1.LabelSelector{
 | 
				
			||||||
 | 
							MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
						sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err := client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(&admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
						_, err := createValidatingWebhookConfiguration(f, &admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: configName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -452,6 +441,10 @@ func registerWebhook(f *framework.Framework, context *certContext) func() {
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				Name: "deny-unwanted-configmap-data.k8s.io",
 | 
									Name: "deny-unwanted-configmap-data.k8s.io",
 | 
				
			||||||
@@ -465,6 +458,7 @@ func registerWebhook(f *framework.Framework, context *certContext) func() {
 | 
				
			|||||||
				}},
 | 
									}},
 | 
				
			||||||
				// The webhook skips the namespace that has label "skip-webhook-admission":"yes"
 | 
									// The webhook skips the namespace that has label "skip-webhook-admission":"yes"
 | 
				
			||||||
				NamespaceSelector: &metav1.LabelSelector{
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
					MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
										MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							Key:      skipNamespaceLabelKey,
 | 
												Key:      skipNamespaceLabelKey,
 | 
				
			||||||
@@ -500,15 +494,14 @@ func registerWebhook(f *framework.Framework, context *certContext) func() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func registerWebhookForAttachingPod(f *framework.Framework, context *certContext) func() {
 | 
					func registerWebhookForAttachingPod(f *framework.Framework, configName string, context *certContext) func() {
 | 
				
			||||||
	client := f.ClientSet
 | 
						client := f.ClientSet
 | 
				
			||||||
	ginkgo.By("Registering the webhook via the AdmissionRegistration API")
 | 
						ginkgo.By("Registering the webhook via the AdmissionRegistration API")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace := f.Namespace.Name
 | 
						namespace := f.Namespace.Name
 | 
				
			||||||
	configName := attachingPodWebhookConfigName
 | 
					 | 
				
			||||||
	sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
						sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err := client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(&admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
						_, err := createValidatingWebhookConfiguration(f, &admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: configName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -534,6 +527,10 @@ func registerWebhookForAttachingPod(f *framework.Framework, context *certContext
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -547,15 +544,14 @@ func registerWebhookForAttachingPod(f *framework.Framework, context *certContext
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func registerMutatingWebhookForConfigMap(f *framework.Framework, context *certContext) func() {
 | 
					func registerMutatingWebhookForConfigMap(f *framework.Framework, configName string, context *certContext) func() {
 | 
				
			||||||
	client := f.ClientSet
 | 
						client := f.ClientSet
 | 
				
			||||||
	ginkgo.By("Registering the mutating configmap webhook via the AdmissionRegistration API")
 | 
						ginkgo.By("Registering the mutating configmap webhook via the AdmissionRegistration API")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace := f.Namespace.Name
 | 
						namespace := f.Namespace.Name
 | 
				
			||||||
	configName := mutatingWebhookConfigName
 | 
					 | 
				
			||||||
	sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
						sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err := client.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(&admissionregistrationv1.MutatingWebhookConfiguration{
 | 
						_, err := createMutatingWebhookConfiguration(f, &admissionregistrationv1.MutatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: configName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -581,6 +577,10 @@ func registerMutatingWebhookForConfigMap(f *framework.Framework, context *certCo
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				Name: "adding-configmap-data-stage-2.k8s.io",
 | 
									Name: "adding-configmap-data-stage-2.k8s.io",
 | 
				
			||||||
@@ -603,6 +603,10 @@ func registerMutatingWebhookForConfigMap(f *framework.Framework, context *certCo
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -629,15 +633,14 @@ func testMutatingConfigMapWebhook(f *framework.Framework) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func registerMutatingWebhookForPod(f *framework.Framework, context *certContext) func() {
 | 
					func registerMutatingWebhookForPod(f *framework.Framework, configName string, context *certContext) func() {
 | 
				
			||||||
	client := f.ClientSet
 | 
						client := f.ClientSet
 | 
				
			||||||
	ginkgo.By("Registering the mutating pod webhook via the AdmissionRegistration API")
 | 
						ginkgo.By("Registering the mutating pod webhook via the AdmissionRegistration API")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace := f.Namespace.Name
 | 
						namespace := f.Namespace.Name
 | 
				
			||||||
	configName := podMutatingWebhookConfigName
 | 
					 | 
				
			||||||
	sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
						sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err := client.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(&admissionregistrationv1.MutatingWebhookConfiguration{
 | 
						_, err := createMutatingWebhookConfiguration(f, &admissionregistrationv1.MutatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: configName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -663,6 +666,10 @@ func registerMutatingWebhookForPod(f *framework.Framework, context *certContext)
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -791,6 +798,7 @@ func testWebhook(f *framework.Framework) {
 | 
				
			|||||||
		Name: skippedNamespaceName,
 | 
							Name: skippedNamespaceName,
 | 
				
			||||||
		Labels: map[string]string{
 | 
							Labels: map[string]string{
 | 
				
			||||||
			skipNamespaceLabelKey: skipNamespaceLabelValue,
 | 
								skipNamespaceLabelKey: skipNamespaceLabelValue,
 | 
				
			||||||
 | 
								f.UniqueName:          "true",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}})
 | 
						}})
 | 
				
			||||||
	framework.ExpectNoError(err, "creating namespace %q", skippedNamespaceName)
 | 
						framework.ExpectNoError(err, "creating namespace %q", skippedNamespaceName)
 | 
				
			||||||
@@ -882,17 +890,16 @@ func failingWebhook(namespace, name string) admissionregistrationv1.ValidatingWe
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func registerFailClosedWebhook(f *framework.Framework, context *certContext) func() {
 | 
					func registerFailClosedWebhook(f *framework.Framework, configName string, context *certContext) func() {
 | 
				
			||||||
	client := f.ClientSet
 | 
					 | 
				
			||||||
	ginkgo.By("Registering a webhook that server cannot talk to, with fail closed policy, via the AdmissionRegistration API")
 | 
						ginkgo.By("Registering a webhook that server cannot talk to, with fail closed policy, via the AdmissionRegistration API")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace := f.Namespace.Name
 | 
						namespace := f.Namespace.Name
 | 
				
			||||||
	configName := webhookFailClosedConfigName
 | 
					 | 
				
			||||||
	// A webhook that cannot talk to server, with fail-closed policy
 | 
						// A webhook that cannot talk to server, with fail-closed policy
 | 
				
			||||||
	policyFail := admissionregistrationv1.Fail
 | 
						policyFail := admissionregistrationv1.Fail
 | 
				
			||||||
	hook := failingWebhook(namespace, "fail-closed.k8s.io")
 | 
						hook := failingWebhook(namespace, "fail-closed.k8s.io")
 | 
				
			||||||
	hook.FailurePolicy = &policyFail
 | 
						hook.FailurePolicy = &policyFail
 | 
				
			||||||
	hook.NamespaceSelector = &metav1.LabelSelector{
 | 
						hook.NamespaceSelector = &metav1.LabelSelector{
 | 
				
			||||||
 | 
							MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
		MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
							MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				Key:      failNamespaceLabelKey,
 | 
									Key:      failNamespaceLabelKey,
 | 
				
			||||||
@@ -902,7 +909,7 @@ func registerFailClosedWebhook(f *framework.Framework, context *certContext) fun
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err := client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(&admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
						_, err := createValidatingWebhookConfiguration(f, &admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: configName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -928,6 +935,7 @@ func testFailClosedWebhook(f *framework.Framework) {
 | 
				
			|||||||
		Name: failNamespaceName,
 | 
							Name: failNamespaceName,
 | 
				
			||||||
		Labels: map[string]string{
 | 
							Labels: map[string]string{
 | 
				
			||||||
			failNamespaceLabelKey: failNamespaceLabelValue,
 | 
								failNamespaceLabelKey: failNamespaceLabelValue,
 | 
				
			||||||
 | 
								f.UniqueName:          "true",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}})
 | 
						}})
 | 
				
			||||||
	framework.ExpectNoError(err, "creating namespace %q", failNamespaceName)
 | 
						framework.ExpectNoError(err, "creating namespace %q", failNamespaceName)
 | 
				
			||||||
@@ -946,20 +954,19 @@ func testFailClosedWebhook(f *framework.Framework) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func registerValidatingWebhookForWebhookConfigurations(f *framework.Framework, context *certContext) func() {
 | 
					func registerValidatingWebhookForWebhookConfigurations(f *framework.Framework, configName string, context *certContext) func() {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	client := f.ClientSet
 | 
						client := f.ClientSet
 | 
				
			||||||
	ginkgo.By("Registering a validating webhook on ValidatingWebhookConfiguration and MutatingWebhookConfiguration objects, via the AdmissionRegistration API")
 | 
						ginkgo.By("Registering a validating webhook on ValidatingWebhookConfiguration and MutatingWebhookConfiguration objects, via the AdmissionRegistration API")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace := f.Namespace.Name
 | 
						namespace := f.Namespace.Name
 | 
				
			||||||
	configName := validatingWebhookForWebhooksConfigName
 | 
					 | 
				
			||||||
	failurePolicy := admissionregistrationv1.Fail
 | 
						failurePolicy := admissionregistrationv1.Fail
 | 
				
			||||||
	sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
						sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// This webhook denies all requests to Delete validating webhook configuration and
 | 
						// This webhook denies all requests to Delete validating webhook configuration and
 | 
				
			||||||
	// mutating webhook configuration objects. It should never be called, however, because
 | 
						// mutating webhook configuration objects. It should never be called, however, because
 | 
				
			||||||
	// dynamic admission webhooks should not be called on requests involving webhook configuration objects.
 | 
						// dynamic admission webhooks should not be called on requests involving webhook configuration objects.
 | 
				
			||||||
	_, err = client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(&admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
						_, err = createValidatingWebhookConfiguration(f, &admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: configName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -989,6 +996,10 @@ func registerValidatingWebhookForWebhookConfigurations(f *framework.Framework, c
 | 
				
			|||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
				FailurePolicy:           &failurePolicy,
 | 
									FailurePolicy:           &failurePolicy,
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -1002,20 +1013,19 @@ func registerValidatingWebhookForWebhookConfigurations(f *framework.Framework, c
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func registerMutatingWebhookForWebhookConfigurations(f *framework.Framework, context *certContext) func() {
 | 
					func registerMutatingWebhookForWebhookConfigurations(f *framework.Framework, configName string, context *certContext) func() {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	client := f.ClientSet
 | 
						client := f.ClientSet
 | 
				
			||||||
	ginkgo.By("Registering a mutating webhook on ValidatingWebhookConfiguration and MutatingWebhookConfiguration objects, via the AdmissionRegistration API")
 | 
						ginkgo.By("Registering a mutating webhook on ValidatingWebhookConfiguration and MutatingWebhookConfiguration objects, via the AdmissionRegistration API")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace := f.Namespace.Name
 | 
						namespace := f.Namespace.Name
 | 
				
			||||||
	configName := mutatingWebhookForWebhooksConfigName
 | 
					 | 
				
			||||||
	failurePolicy := admissionregistrationv1.Fail
 | 
						failurePolicy := admissionregistrationv1.Fail
 | 
				
			||||||
	sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
						sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// This webhook adds a label to all requests create to validating webhook configuration and
 | 
						// This webhook adds a label to all requests create to validating webhook configuration and
 | 
				
			||||||
	// mutating webhook configuration objects. It should never be called, however, because
 | 
						// mutating webhook configuration objects. It should never be called, however, because
 | 
				
			||||||
	// dynamic admission webhooks should not be called on requests involving webhook configuration objects.
 | 
						// dynamic admission webhooks should not be called on requests involving webhook configuration objects.
 | 
				
			||||||
	_, err = client.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(&admissionregistrationv1.MutatingWebhookConfiguration{
 | 
						_, err = createMutatingWebhookConfiguration(f, &admissionregistrationv1.MutatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: configName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -1045,6 +1055,10 @@ func registerMutatingWebhookForWebhookConfigurations(f *framework.Framework, con
 | 
				
			|||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
				FailurePolicy:           &failurePolicy,
 | 
									FailurePolicy:           &failurePolicy,
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -1061,7 +1075,7 @@ func registerMutatingWebhookForWebhookConfigurations(f *framework.Framework, con
 | 
				
			|||||||
// This test assumes that the deletion-rejecting webhook defined in
 | 
					// This test assumes that the deletion-rejecting webhook defined in
 | 
				
			||||||
// registerValidatingWebhookForWebhookConfigurations and the webhook-config-mutating
 | 
					// registerValidatingWebhookForWebhookConfigurations and the webhook-config-mutating
 | 
				
			||||||
// webhook defined in registerMutatingWebhookForWebhookConfigurations already exist.
 | 
					// webhook defined in registerMutatingWebhookForWebhookConfigurations already exist.
 | 
				
			||||||
func testWebhooksForWebhookConfigurations(f *framework.Framework) {
 | 
					func testWebhooksForWebhookConfigurations(f *framework.Framework, configName string) {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	client := f.ClientSet
 | 
						client := f.ClientSet
 | 
				
			||||||
	ginkgo.By("Creating a dummy validating-webhook-configuration object")
 | 
						ginkgo.By("Creating a dummy validating-webhook-configuration object")
 | 
				
			||||||
@@ -1070,9 +1084,9 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) {
 | 
				
			|||||||
	failurePolicy := admissionregistrationv1.Ignore
 | 
						failurePolicy := admissionregistrationv1.Ignore
 | 
				
			||||||
	sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
						sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutatedValidatingWebhookConfiguration, err := client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(&admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
						mutatedValidatingWebhookConfiguration, err := createValidatingWebhookConfiguration(f, &admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: dummyValidatingWebhookConfigName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		Webhooks: []admissionregistrationv1.ValidatingWebhook{
 | 
							Webhooks: []admissionregistrationv1.ValidatingWebhook{
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
@@ -1102,12 +1116,16 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) {
 | 
				
			|||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
				FailurePolicy:           &failurePolicy,
 | 
									FailurePolicy:           &failurePolicy,
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	framework.ExpectNoError(err, "registering webhook config %s with namespace %s", dummyValidatingWebhookConfigName, namespace)
 | 
						framework.ExpectNoError(err, "registering webhook config %s with namespace %s", configName, namespace)
 | 
				
			||||||
	if mutatedValidatingWebhookConfiguration.ObjectMeta.Labels != nil && mutatedValidatingWebhookConfiguration.ObjectMeta.Labels[addedLabelKey] == addedLabelValue {
 | 
						if mutatedValidatingWebhookConfiguration.ObjectMeta.Labels != nil && mutatedValidatingWebhookConfiguration.ObjectMeta.Labels[addedLabelKey] == addedLabelValue {
 | 
				
			||||||
		e2elog.Failf("expected %s not to be mutated by mutating webhooks but it was", dummyValidatingWebhookConfigName)
 | 
							e2elog.Failf("expected %s not to be mutated by mutating webhooks but it was", configName)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The webhook configuration is honored in 10s.
 | 
						// The webhook configuration is honored in 10s.
 | 
				
			||||||
@@ -1115,14 +1133,14 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	ginkgo.By("Deleting the validating-webhook-configuration, which should be possible to remove")
 | 
						ginkgo.By("Deleting the validating-webhook-configuration, which should be possible to remove")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Delete(dummyValidatingWebhookConfigName, nil)
 | 
						err = client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Delete(configName, nil)
 | 
				
			||||||
	framework.ExpectNoError(err, "deleting webhook config %s with namespace %s", dummyValidatingWebhookConfigName, namespace)
 | 
						framework.ExpectNoError(err, "deleting webhook config %s with namespace %s", configName, namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ginkgo.By("Creating a dummy mutating-webhook-configuration object")
 | 
						ginkgo.By("Creating a dummy mutating-webhook-configuration object")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutatedMutatingWebhookConfiguration, err := client.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(&admissionregistrationv1.MutatingWebhookConfiguration{
 | 
						mutatedMutatingWebhookConfiguration, err := createMutatingWebhookConfiguration(f, &admissionregistrationv1.MutatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: dummyMutatingWebhookConfigName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		Webhooks: []admissionregistrationv1.MutatingWebhook{
 | 
							Webhooks: []admissionregistrationv1.MutatingWebhook{
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
@@ -1152,12 +1170,16 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) {
 | 
				
			|||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
				FailurePolicy:           &failurePolicy,
 | 
									FailurePolicy:           &failurePolicy,
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	framework.ExpectNoError(err, "registering webhook config %s with namespace %s", dummyMutatingWebhookConfigName, namespace)
 | 
						framework.ExpectNoError(err, "registering webhook config %s with namespace %s", configName, namespace)
 | 
				
			||||||
	if mutatedMutatingWebhookConfiguration.ObjectMeta.Labels != nil && mutatedMutatingWebhookConfiguration.ObjectMeta.Labels[addedLabelKey] == addedLabelValue {
 | 
						if mutatedMutatingWebhookConfiguration.ObjectMeta.Labels != nil && mutatedMutatingWebhookConfiguration.ObjectMeta.Labels[addedLabelKey] == addedLabelValue {
 | 
				
			||||||
		e2elog.Failf("expected %s not to be mutated by mutating webhooks but it was", dummyMutatingWebhookConfigName)
 | 
							e2elog.Failf("expected %s not to be mutated by mutating webhooks but it was", configName)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The webhook configuration is honored in 10s.
 | 
						// The webhook configuration is honored in 10s.
 | 
				
			||||||
@@ -1165,8 +1187,8 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	ginkgo.By("Deleting the mutating-webhook-configuration, which should be possible to remove")
 | 
						ginkgo.By("Deleting the mutating-webhook-configuration, which should be possible to remove")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = client.AdmissionregistrationV1().MutatingWebhookConfigurations().Delete(dummyMutatingWebhookConfigName, nil)
 | 
						err = client.AdmissionregistrationV1().MutatingWebhookConfigurations().Delete(configName, nil)
 | 
				
			||||||
	framework.ExpectNoError(err, "deleting webhook config %s with namespace %s", dummyMutatingWebhookConfigName, namespace)
 | 
						framework.ExpectNoError(err, "deleting webhook config %s with namespace %s", configName, namespace)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func createNamespace(f *framework.Framework, ns *v1.Namespace) error {
 | 
					func createNamespace(f *framework.Framework, ns *v1.Namespace) error {
 | 
				
			||||||
@@ -1324,15 +1346,14 @@ func cleanWebhookTest(client clientset.Interface, namespaceName string) {
 | 
				
			|||||||
	_ = client.RbacV1().RoleBindings("kube-system").Delete(roleBindingName, nil)
 | 
						_ = client.RbacV1().RoleBindings("kube-system").Delete(roleBindingName, nil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func registerWebhookForCustomResource(f *framework.Framework, context *certContext, testcrd *crd.TestCrd) func() {
 | 
					func registerWebhookForCustomResource(f *framework.Framework, configName string, context *certContext, testcrd *crd.TestCrd) func() {
 | 
				
			||||||
	client := f.ClientSet
 | 
						client := f.ClientSet
 | 
				
			||||||
	ginkgo.By("Registering the custom resource webhook via the AdmissionRegistration API")
 | 
						ginkgo.By("Registering the custom resource webhook via the AdmissionRegistration API")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace := f.Namespace.Name
 | 
						namespace := f.Namespace.Name
 | 
				
			||||||
	configName := crWebhookConfigName
 | 
					 | 
				
			||||||
	sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
						sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err := client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(&admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
						_, err := createValidatingWebhookConfiguration(f, &admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: configName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -1358,6 +1379,10 @@ func registerWebhookForCustomResource(f *framework.Framework, context *certConte
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -1370,15 +1395,14 @@ func registerWebhookForCustomResource(f *framework.Framework, context *certConte
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func registerMutatingWebhookForCustomResource(f *framework.Framework, context *certContext, testcrd *crd.TestCrd) func() {
 | 
					func registerMutatingWebhookForCustomResource(f *framework.Framework, configName string, context *certContext, testcrd *crd.TestCrd) func() {
 | 
				
			||||||
	client := f.ClientSet
 | 
						client := f.ClientSet
 | 
				
			||||||
	ginkgo.By(fmt.Sprintf("Registering the mutating webhook for custom resource %s via the AdmissionRegistration API", testcrd.Crd.Name))
 | 
						ginkgo.By(fmt.Sprintf("Registering the mutating webhook for custom resource %s via the AdmissionRegistration API", testcrd.Crd.Name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace := f.Namespace.Name
 | 
						namespace := f.Namespace.Name
 | 
				
			||||||
	configName := f.UniqueName
 | 
					 | 
				
			||||||
	sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
						sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err := client.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(&admissionregistrationv1.MutatingWebhookConfiguration{
 | 
						_, err := createMutatingWebhookConfiguration(f, &admissionregistrationv1.MutatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: configName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -1404,6 +1428,10 @@ func registerMutatingWebhookForCustomResource(f *framework.Framework, context *c
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				Name: "mutate-custom-resource-data-stage-2.k8s.io",
 | 
									Name: "mutate-custom-resource-data-stage-2.k8s.io",
 | 
				
			||||||
@@ -1426,6 +1454,10 @@ func registerMutatingWebhookForCustomResource(f *framework.Framework, context *c
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -1566,19 +1598,18 @@ func testMultiVersionCustomResourceWebhook(f *framework.Framework, testcrd *crd.
 | 
				
			|||||||
	framework.ExpectNoError(err, "failed to patch custom resource %s in namespace: %s", crName, f.Namespace.Name)
 | 
						framework.ExpectNoError(err, "failed to patch custom resource %s in namespace: %s", crName, f.Namespace.Name)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func registerValidatingWebhookForCRD(f *framework.Framework, context *certContext) func() {
 | 
					func registerValidatingWebhookForCRD(f *framework.Framework, configName string, context *certContext) func() {
 | 
				
			||||||
	client := f.ClientSet
 | 
						client := f.ClientSet
 | 
				
			||||||
	ginkgo.By("Registering the crd webhook via the AdmissionRegistration API")
 | 
						ginkgo.By("Registering the crd webhook via the AdmissionRegistration API")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace := f.Namespace.Name
 | 
						namespace := f.Namespace.Name
 | 
				
			||||||
	configName := crdWebhookConfigName
 | 
					 | 
				
			||||||
	sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
						sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// This webhook will deny the creation of CustomResourceDefinitions which have the
 | 
						// This webhook will deny the creation of CustomResourceDefinitions which have the
 | 
				
			||||||
	// label "webhook-e2e-test":"webhook-disallow"
 | 
						// label "webhook-e2e-test":"webhook-disallow"
 | 
				
			||||||
	// NOTE: Because tests are run in parallel and in an unpredictable order, it is critical
 | 
						// NOTE: Because tests are run in parallel and in an unpredictable order, it is critical
 | 
				
			||||||
	// that no other test attempts to create CRD with that label.
 | 
						// that no other test attempts to create CRD with that label.
 | 
				
			||||||
	_, err := client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(&admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
						_, err := createValidatingWebhookConfiguration(f, &admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: configName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -1604,6 +1635,10 @@ func registerValidatingWebhookForCRD(f *framework.Framework, context *certContex
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				SideEffects:             &sideEffectsNone,
 | 
									SideEffects:             &sideEffectsNone,
 | 
				
			||||||
				AdmissionReviewVersions: []string{"v1beta1"},
 | 
									AdmissionReviewVersions: []string{"v1beta1"},
 | 
				
			||||||
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -1669,13 +1704,8 @@ func testCRDDenyWebhook(f *framework.Framework) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func registerSlowWebhook(f *framework.Framework, context *certContext, policy *admissionregistrationv1.FailurePolicyType, timeout *int32) func() {
 | 
					func labelNamespace(f *framework.Framework, namespace string) {
 | 
				
			||||||
	client := f.ClientSet
 | 
						client := f.ClientSet
 | 
				
			||||||
	ginkgo.By("Registering slow webhook via the AdmissionRegistration API")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	namespace := f.Namespace.Name
 | 
					 | 
				
			||||||
	configName := slowWebhookConfigName
 | 
					 | 
				
			||||||
	sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add a unique label to the namespace
 | 
						// Add a unique label to the namespace
 | 
				
			||||||
	ns, err := client.CoreV1().Namespaces().Get(namespace, metav1.GetOptions{})
 | 
						ns, err := client.CoreV1().Namespaces().Get(namespace, metav1.GetOptions{})
 | 
				
			||||||
@@ -1683,11 +1713,19 @@ func registerSlowWebhook(f *framework.Framework, context *certContext, policy *a
 | 
				
			|||||||
	if ns.Labels == nil {
 | 
						if ns.Labels == nil {
 | 
				
			||||||
		ns.Labels = map[string]string{}
 | 
							ns.Labels = map[string]string{}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ns.Labels[slowWebhookConfigName] = namespace
 | 
						ns.Labels[f.UniqueName] = "true"
 | 
				
			||||||
	_, err = client.CoreV1().Namespaces().Update(ns)
 | 
						_, err = client.CoreV1().Namespaces().Update(ns)
 | 
				
			||||||
	framework.ExpectNoError(err, "error labeling namespace %s", namespace)
 | 
						framework.ExpectNoError(err, "error labeling namespace %s", namespace)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(&admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
					func registerSlowWebhook(f *framework.Framework, configName string, context *certContext, policy *admissionregistrationv1.FailurePolicyType, timeout *int32) func() {
 | 
				
			||||||
 | 
						client := f.ClientSet
 | 
				
			||||||
 | 
						ginkgo.By("Registering slow webhook via the AdmissionRegistration API")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						namespace := f.Namespace.Name
 | 
				
			||||||
 | 
						sideEffectsNone := admissionregistrationv1.SideEffectClassNone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := createValidatingWebhookConfiguration(f, &admissionregistrationv1.ValidatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: configName,
 | 
								Name: configName,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -1713,7 +1751,7 @@ func registerSlowWebhook(f *framework.Framework, context *certContext, policy *a
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				// Scope the webhook to just this namespace
 | 
									// Scope the webhook to just this namespace
 | 
				
			||||||
				NamespaceSelector: &metav1.LabelSelector{
 | 
									NamespaceSelector: &metav1.LabelSelector{
 | 
				
			||||||
					MatchLabels: ns.Labels,
 | 
										MatchLabels: map[string]string{f.UniqueName: "true"},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				FailurePolicy:           policy,
 | 
									FailurePolicy:           policy,
 | 
				
			||||||
				TimeoutSeconds:          timeout,
 | 
									TimeoutSeconds:          timeout,
 | 
				
			||||||
@@ -1783,3 +1821,33 @@ func servedAPIVersions(crd *apiextensionsv1beta1.CustomResourceDefinition) []str
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return ret
 | 
						return ret
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// createValidatingWebhookConfiguration ensures the webhook config scopes object or namespace selection
 | 
				
			||||||
 | 
					// to avoid interfering with other tests, then creates the config.
 | 
				
			||||||
 | 
					func createValidatingWebhookConfiguration(f *framework.Framework, config *admissionregistrationv1.ValidatingWebhookConfiguration) (*admissionregistrationv1.ValidatingWebhookConfiguration, error) {
 | 
				
			||||||
 | 
						for _, webhook := range config.Webhooks {
 | 
				
			||||||
 | 
							if webhook.NamespaceSelector != nil && webhook.NamespaceSelector.MatchLabels[f.UniqueName] == "true" {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if webhook.ObjectSelector != nil && webhook.ObjectSelector.MatchLabels[f.UniqueName] == "true" {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							e2elog.Failf(`webhook %s in config %s has no namespace or object selector with %s="true", and can interfere with other tests`, webhook.Name, config.Name, f.UniqueName)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return f.ClientSet.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(config)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// createMutatingWebhookConfiguration ensures the webhook config scopes object or namespace selection
 | 
				
			||||||
 | 
					// to avoid interfering with other tests, then creates the config.
 | 
				
			||||||
 | 
					func createMutatingWebhookConfiguration(f *framework.Framework, config *admissionregistrationv1.MutatingWebhookConfiguration) (*admissionregistrationv1.MutatingWebhookConfiguration, error) {
 | 
				
			||||||
 | 
						for _, webhook := range config.Webhooks {
 | 
				
			||||||
 | 
							if webhook.NamespaceSelector != nil && webhook.NamespaceSelector.MatchLabels[f.UniqueName] == "true" {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if webhook.ObjectSelector != nil && webhook.ObjectSelector.MatchLabels[f.UniqueName] == "true" {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							e2elog.Failf(`webhook %s in config %s has no namespace or object selector with %s="true", and can interfere with other tests`, webhook.Name, config.Name, f.UniqueName)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return f.ClientSet.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(config)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user