Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automated cherry pick of #61609: Cleanup CRD/CR confusion in webhook e2e tests #62350: Fix flaky crd e2e tests #62559

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 62 additions & 50 deletions test/e2e/apimachinery/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,29 +46,29 @@ import (
)

const (
secretName = "sample-webhook-secret"
deploymentName = "sample-webhook-deployment"
serviceName = "e2e-test-webhook"
roleBindingName = "webhook-auth-reader"
webhookConfigName = "e2e-test-webhook-config"
mutatingWebhookConfigName = "e2e-test-mutating-webhook-config"
skipNamespaceLabelKey = "skip-webhook-admission"
skipNamespaceLabelValue = "yes"
skippedNamespaceName = "exempted-namesapce"
disallowedPodName = "disallowed-pod"
disallowedConfigMapName = "disallowed-configmap"
allowedConfigMapName = "allowed-configmap"
crdName = "e2e-test-webhook-crd"
crdKind = "E2e-test-webhook-crd"
crWebhookConfigName = "e2e-test-webhook-config-cr"
crdWebhookConfigName = "e2e-test-webhook-config-crd"
crdMutatingWebhookConfigName = "e2e-test-mutating-webhook-config-crd"
crdAPIGroup = "webhook-crd-test.k8s.io"
crdAPIVersion = "v1"
webhookFailClosedConfigName = "e2e-test-webhook-fail-closed"
failNamespaceLabelKey = "fail-closed-webhook"
failNamespaceLabelValue = "yes"
failNamespaceName = "fail-closed-namesapce"
secretName = "sample-webhook-secret"
deploymentName = "sample-webhook-deployment"
serviceName = "e2e-test-webhook"
roleBindingName = "webhook-auth-reader"
webhookConfigName = "e2e-test-webhook-config"
mutatingWebhookConfigName = "e2e-test-mutating-webhook-config"
skipNamespaceLabelKey = "skip-webhook-admission"
skipNamespaceLabelValue = "yes"
skippedNamespaceName = "exempted-namesapce"
disallowedPodName = "disallowed-pod"
disallowedConfigMapName = "disallowed-configmap"
allowedConfigMapName = "allowed-configmap"
crdName = "e2e-test-webhook-crd"
crdKind = "E2e-test-webhook-crd"
crWebhookConfigName = "e2e-test-webhook-config-cr"
crdWebhookConfigName = "e2e-test-webhook-config-crd"
crMutatingWebhookConfigName = "e2e-test-mutating-webhook-config-cr"
crdAPIGroup = "webhook-crd-test.k8s.io"
crdAPIVersion = "v1"
webhookFailClosedConfigName = "e2e-test-webhook-fail-closed"
failNamespaceLabelKey = "fail-closed-webhook"
failNamespaceLabelValue = "yes"
failNamespaceName = "fail-closed-namesapce"
)

var serverWebhookVersion = utilversion.MustParseSemantic("v1.8.0")
Expand Down Expand Up @@ -100,7 +100,7 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
// 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, "gcr.io/kubernetes-e2e-test-images/k8s-sample-admission-webhook-amd64:1.9v2", context)
deployWebhookAndService(f, "gcr.io/kubernetes-e2e-test-images/k8s-sample-admission-webhook-amd64:1.10v2", context)
})
AfterEach(func() {
cleanWebhookTest(client, namespaceName)
Expand All @@ -117,7 +117,7 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
defer crdCleanup()
registerWebhookForCustomResource(f, context)
defer client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Delete(crWebhookConfigName, nil)
testCRDWebhook(f, dynamicClient)
testCustomResourceWebhook(f, dynamicClient)
})

It("Should unconditionally reject operations on fail closed webhook", func() {
Expand All @@ -138,12 +138,12 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
testMutatingPodWebhook(f)
})

It("Should mutate crd", func() {
It("Should mutate custom resource", func() {
crdCleanup, dynamicClient := createCRD(f)
defer crdCleanup()
registerMutatingWebhookForCRD(f, context)
defer client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Delete(crdMutatingWebhookConfigName, nil)
testMutatingCRDWebhook(f, dynamicClient)
registerMutatingWebhookForCustomResource(f, context)
defer client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Delete(crMutatingWebhookConfigName, nil)
testMutatingCustomResourceWebhook(f, dynamicClient)
})

It("Should deny crd creation", func() {
Expand Down Expand Up @@ -824,16 +824,17 @@ func createCRD(f *framework.Framework) (func(), dynamic.ResourceInterface) {

func registerWebhookForCustomResource(f *framework.Framework, context *certContext) {
client := f.ClientSet
By("Registering the crd webhook via the AdmissionRegistration API")
By("Registering the custom resource webhook via the AdmissionRegistration API")

namespace := f.Namespace.Name
configName := crWebhookConfigName
_, err := client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Create(&v1beta1.ValidatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: crWebhookConfigName,
Name: configName,
},
Webhooks: []v1beta1.Webhook{
{
Name: "deny-unwanted-crd-data.k8s.io",
Name: "deny-unwanted-custom-resource-data.k8s.io",
Rules: []v1beta1.RuleWithOperations{{
Operations: []v1beta1.OperationType{v1beta1.Create},
Rule: v1beta1.Rule{
Expand All @@ -846,31 +847,32 @@ func registerWebhookForCustomResource(f *framework.Framework, context *certConte
Service: &v1beta1.ServiceReference{
Namespace: namespace,
Name: serviceName,
Path: strPtr("/crd"),
Path: strPtr("/custom-resource"),
},
CABundle: context.signingCert,
},
},
},
})
framework.ExpectNoError(err, "registering crd webhook config %s with namespace %s", webhookConfigName, namespace)
framework.ExpectNoError(err, "registering custom resource webhook config %s with namespace %s", configName, namespace)

// The webhook configuration is honored in 1s.
time.Sleep(10 * time.Second)
}

func registerMutatingWebhookForCRD(f *framework.Framework, context *certContext) {
func registerMutatingWebhookForCustomResource(f *framework.Framework, context *certContext) {
client := f.ClientSet
By("Registering the mutating webhook for crd via the AdmissionRegistration API")
By("Registering the mutating webhook for a custom resource via the AdmissionRegistration API")

namespace := f.Namespace.Name
configName := crMutatingWebhookConfigName
_, err := client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Create(&v1beta1.MutatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: crdMutatingWebhookConfigName,
Name: configName,
},
Webhooks: []v1beta1.Webhook{
{
Name: "mutate-crd-data-stage-1.k8s.io",
Name: "mutate-custom-resource-data-stage-1.k8s.io",
Rules: []v1beta1.RuleWithOperations{{
Operations: []v1beta1.OperationType{v1beta1.Create},
Rule: v1beta1.Rule{
Expand All @@ -883,13 +885,13 @@ func registerMutatingWebhookForCRD(f *framework.Framework, context *certContext)
Service: &v1beta1.ServiceReference{
Namespace: namespace,
Name: serviceName,
Path: strPtr("/mutating-crd"),
Path: strPtr("/mutating-custom-resource"),
},
CABundle: context.signingCert,
},
},
{
Name: "mutate-crd-data-stage-2.k8s.io",
Name: "mutate-custom-resource-data-stage-2.k8s.io",
Rules: []v1beta1.RuleWithOperations{{
Operations: []v1beta1.OperationType{v1beta1.Create},
Rule: v1beta1.Rule{
Expand All @@ -902,20 +904,20 @@ func registerMutatingWebhookForCRD(f *framework.Framework, context *certContext)
Service: &v1beta1.ServiceReference{
Namespace: namespace,
Name: serviceName,
Path: strPtr("/mutating-crd"),
Path: strPtr("/mutating-custom-resource"),
},
CABundle: context.signingCert,
},
},
},
})
framework.ExpectNoError(err, "registering crd webhook config %s with namespace %s", crdMutatingWebhookConfigName, namespace)
framework.ExpectNoError(err, "registering custom resource webhook config %s with namespace %s", configName, namespace)

// The webhook configuration is honored in 1s.
time.Sleep(10 * time.Second)
}

func testCRDWebhook(f *framework.Framework, crdClient dynamic.ResourceInterface) {
func testCustomResourceWebhook(f *framework.Framework, customResourceClient dynamic.ResourceInterface) {
By("Creating a custom resource that should be denied by the webhook")
crd := newCRDForAdmissionWebhookTest()
crInstance := &unstructured.Unstructured{
Expand All @@ -931,15 +933,15 @@ func testCRDWebhook(f *framework.Framework, crdClient dynamic.ResourceInterface)
},
},
}
_, err := crdClient.Create(crInstance)
_, err := customResourceClient.Create(crInstance)
Expect(err).NotTo(BeNil())
expectedErrMsg := "the custom resource contains unwanted data"
if !strings.Contains(err.Error(), expectedErrMsg) {
framework.Failf("expect error contains %q, got %q", expectedErrMsg, err.Error())
}
}

func testMutatingCRDWebhook(f *framework.Framework, crdClient dynamic.ResourceInterface) {
func testMutatingCustomResourceWebhook(f *framework.Framework, customResourceClient dynamic.ResourceInterface) {
By("Creating a custom resource that should be mutated by the webhook")
crd := newCRDForAdmissionWebhookTest()
cr := &unstructured.Unstructured{
Expand All @@ -955,7 +957,7 @@ func testMutatingCRDWebhook(f *framework.Framework, crdClient dynamic.ResourceIn
},
},
}
mutatedCR, err := crdClient.Create(cr)
mutatedCR, err := customResourceClient.Create(cr)
Expect(err).To(BeNil())
expectedCRData := map[string]interface{}{
"mutation-start": "yes",
Expand All @@ -973,13 +975,18 @@ func registerValidatingWebhookForCRD(f *framework.Framework, context *certContex

namespace := f.Namespace.Name
configName := crdWebhookConfigName

// This webhook will deny the creation of CustomResourceDefinitions which have the
// label "webhook-e2e-test":"webhook-disallow"
// 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.
_, err := client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Create(&v1beta1.ValidatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: configName,
},
Webhooks: []v1beta1.Webhook{
{
Name: "deny-crd.k8s.io",
Name: "deny-crd-with-unwanted-label.k8s.io",
Rules: []v1beta1.RuleWithOperations{{
Operations: []v1beta1.OperationType{v1beta1.Create},
Rule: v1beta1.Rule{
Expand All @@ -992,7 +999,7 @@ func registerValidatingWebhookForCRD(f *framework.Framework, context *certContex
Service: &v1beta1.ServiceReference{
Namespace: namespace,
Name: serviceName,
Path: strPtr("/always-deny"),
Path: strPtr("/crd"),
},
CABundle: context.signingCert,
},
Expand Down Expand Up @@ -1027,7 +1034,12 @@ func testCRDDenyWebhook(f *framework.Framework) {
return
}
crd := &apiextensionsv1beta1.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{Name: name + "s." + group},
ObjectMeta: metav1.ObjectMeta{
Name: name + "s." + group,
Labels: map[string]string{
"webhook-e2e-test": "webhook-disallow",
},
},
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
Group: group,
Version: apiVersion,
Expand All @@ -1044,7 +1056,7 @@ func testCRDDenyWebhook(f *framework.Framework) {
// create CRD
_, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd)
Expect(err).NotTo(BeNil())
expectedErrMsg := "this webhook denies all requests"
expectedErrMsg := "the crd contains unwanted label"
if !strings.Contains(err.Error(), expectedErrMsg) {
framework.Failf("expect error contains %q, got %q", expectedErrMsg, err.Error())
}
Expand Down
1 change: 1 addition & 0 deletions test/images/webhook/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ go_library(
"//vendor/k8s.io/api/admission/v1beta1:go_default_library",
"//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
Expand Down
4 changes: 2 additions & 2 deletions test/images/webhook/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

build:
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o webhook .
docker build --no-cache -t gcr.io/kubernetes-e2e-test-images/k8s-sample-admission-webhook-amd64:1.9v1 .
docker build --no-cache -t gcr.io/kubernetes-e2e-test-images/k8s-sample-admission-webhook-amd64:1.10v2 .
rm -rf webhook
push:
gcloud docker -- push gcr.io/kubernetes-e2e-test-images/k8s-sample-admission-webhook-amd64:1.9v1
gcloud docker -- push gcr.io/kubernetes-e2e-test-images/k8s-sample-admission-webhook-amd64:1.10v2
Loading