mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 14:37:00 +00:00
Merge pull request #81032 from liggitt/isolate-webhook-e2e
Scope e2e webhooks to avoid cross-test interference
This commit is contained in:
commit
1d83daf8a7
@ -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)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user