From 8ce1fe52418003d586edcbdf3d719deb3968b951 Mon Sep 17 00:00:00 2001 From: Rita Zhang Date: Tue, 27 Feb 2024 09:07:03 -0800 Subject: [PATCH] update unit test for vap generation; add custom assets for envtest Signed-off-by: Rita Zhang --- Makefile | 16 +- .../constrainttemplate_controller_test.go | 137 +++++++++++------- 2 files changed, 102 insertions(+), 51 deletions(-) diff --git a/Makefile b/Makefile index cdb45b25f70..dff6c675fed 100644 --- a/Makefile +++ b/Makefile @@ -110,9 +110,21 @@ endif all: lint test manager +## Location to install custom assets +CUSTOMENVTEST = $(LOCALBIN)/k8s/1.29.1-linux-amd64 +$(CUSTOMENVTEST): + if [ ! -d "$(CUSTOMENVTEST)" ]; then \ + mkdir -p $(LOCALBIN)/k8s/1.29.1-linux-amd64; \ + curl -L https://sertaccdn.azureedge.net/kube-vap-fix/etcd --output $(LOCALBIN)/k8s/1.29.1-linux-amd64/etcd && chmod +x $(LOCALBIN)/k8s/1.29.1-linux-amd64/etcd; \ + curl -L https://sertaccdn.azureedge.net/kube-vap-fix/kube-apiserver --output $(LOCALBIN)/k8s/1.29.1-linux-amd64/kube-apiserver && chmod +x $(LOCALBIN)/k8s/1.29.1-linux-amd64/kube-apiserver; \ + curl -L https://sertaccdn.azureedge.net/kube-vap-fix/kubectl --output $(LOCALBIN)/k8s/1.29.1-linux-amd64/kubectl && chmod +x $(LOCALBIN)/k8s/1.29.1-linux-amd64/kubectl; \ + fi # Run tests -native-test: envtest - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(KUBERNETES_VERSION) --bin-dir $(LOCALBIN) -p path)" \ +# TODO(ritazh): replace custom asset when new release is available in kubebuilder +# NOTE: custom asset is built from https://github.com/kubernetes/kubernetes/pull/123003 on top of 1.29.1 +# "$(shell $(ENVTEST) use $(KUBERNETES_VERSION) --bin-dir $(LOCALBIN) -p path)" +native-test: $(CUSTOMENVTEST) envtest + KUBEBUILDER_ASSETS="$(CUSTOMENVTEST)" \ GO111MODULE=on \ go test -mod vendor ./pkg/... ./apis/... ./cmd/gator/... -race -bench . -coverprofile cover.out diff --git a/pkg/controller/constrainttemplate/constrainttemplate_controller_test.go b/pkg/controller/constrainttemplate/constrainttemplate_controller_test.go index 32072c717c6..051daa6ad5a 100644 --- a/pkg/controller/constrainttemplate/constrainttemplate_controller_test.go +++ b/pkg/controller/constrainttemplate/constrainttemplate_controller_test.go @@ -342,44 +342,83 @@ func TestReconcile(t *testing.T) { t.Fatal(err) } }) - // TODO(ritazh): uncomment this test after the fix for https://github.com/kubernetes/kubernetes/issues/122658 makes its way to a k8s release - // t.Run("VapBinding should be created", func(t *testing.T) { - // suffix := "VapBindingShouldBeCreated" - - // logger.Info("Running test: VapBinding should be created") - // labels := map[string]string{ - // constraint.VapGenerationLabel: constraint.Yes, - // } - // constraintTemplate := makeReconcileConstraintTemplateForVap(suffix, labels) - // cstr := newDenyAllCstrWithLabel(suffix, labels) - // t.Cleanup(testutils.DeleteObjectAndConfirm(ctx, t, c, expectedCRD(suffix))) - // testutils.CreateThenCleanup(ctx, t, c, constraintTemplate) - - // err = retry.OnError(testutils.ConstantRetry, func(err error) bool { - // return true - // }, func() error { - // // check if vap resource exists now - // vap := &admissionregistrationv1beta1.ValidatingAdmissionPolicy{} - // vapName := fmt.Sprintf("gatekeeper-%s", denyall+strings.ToLower(suffix)) - // if err := c.Get(ctx, types.NamespacedName{Name: vapName}, vap); err != nil { - // return err - // } - // return c.Create(ctx, cstr) - // }) - // if err != nil { - // logger.Error(err, "get vap and create cstr") - // t.Fatal(err) - // } - // logger.Info("cstr created") - // // check if vapbinding resource exists now - // vapBinding := &admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding{} - // vapBindingName := fmt.Sprintf("gatekeeper-%s", denyall+strings.ToLower(suffix)) - // if err := c.Get(ctx, types.NamespacedName{Name: vapBindingName}, vapBinding); err != nil { - // logger.Error(err, "get vapBinding") - // t.Fatal(err) - // } - // logger.Info("vapbinding found") - // }) + t.Run("VapBinding should be created", func(t *testing.T) { + suffix := "VapBindingShouldBeCreated" + + logger.Info("Running test: VapBinding should be created") + labels := map[string]string{ + constraint.VapGenerationLabel: constraint.Yes, + } + constraintTemplate := makeReconcileConstraintTemplateForVap(suffix, labels) + cstr := newDenyAllCstrWithLabel(suffix, labels) + t.Cleanup(testutils.DeleteObjectAndConfirm(ctx, t, c, expectedCRD(suffix))) + testutils.CreateThenCleanup(ctx, t, c, constraintTemplate) + + err = retry.OnError(testutils.ConstantRetry, func(err error) bool { + return true + }, func() error { + // check if vap resource exists now + vap := &admissionregistrationv1beta1.ValidatingAdmissionPolicy{} + vapName := fmt.Sprintf("gatekeeper-%s", denyall+strings.ToLower(suffix)) + if err := c.Get(ctx, types.NamespacedName{Name: vapName}, vap); err != nil { + return err + } + return c.Create(ctx, cstr) + }) + if err != nil { + logger.Error(err, "get vap and create cstr") + t.Fatal(err) + } + // check if vapbinding resource exists now + vapBinding := &admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding{} + vapBindingName := fmt.Sprintf("gatekeeper-%s", denyall+strings.ToLower(suffix)) + if err := c.Get(ctx, types.NamespacedName{Name: vapBindingName}, vapBinding); err != nil { + logger.Error(err, "get vapBinding") + t.Fatal(err) + } + }) + + t.Run("VapBinding should not be created", func(t *testing.T) { + suffix := "VapBindingShouldNotBeCreated" + + logger.Info("Running test: VapBinding should not be created") + labels := map[string]string{ + constraint.VapGenerationLabel: constraint.Yes, + } + constraintLabels := map[string]string{ + constraint.VapGenerationLabel: constraint.No, + } + constraintTemplate := makeReconcileConstraintTemplateForVap(suffix, labels) + cstr := newDenyAllCstrWithLabel(suffix, constraintLabels) + t.Cleanup(testutils.DeleteObjectAndConfirm(ctx, t, c, expectedCRD(suffix))) + testutils.CreateThenCleanup(ctx, t, c, constraintTemplate) + + err = retry.OnError(testutils.ConstantRetry, func(err error) bool { + return true + }, func() error { + // check if vap resource exists now + vap := &admissionregistrationv1beta1.ValidatingAdmissionPolicy{} + vapName := fmt.Sprintf("gatekeeper-%s", denyall+strings.ToLower(suffix)) + if err := c.Get(ctx, types.NamespacedName{Name: vapName}, vap); err != nil { + return err + } + return c.Create(ctx, cstr) + }) + if err != nil { + logger.Error(err, "get vap and create cstr") + t.Fatal(err) + } + // check if vapbinding resource exists now + vapBinding := &admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding{} + vapBindingName := fmt.Sprintf("gatekeeper-%s", denyall+strings.ToLower(suffix)) + if err := c.Get(ctx, types.NamespacedName{Name: vapBindingName}, vapBinding); err != nil { + if !apierrors.IsNotFound(err) { + t.Fatal(err) + } + } else { + t.Fatal("should result in error, vapbinding not found") + } + }) t.Run("Constraint is marked as enforced", func(t *testing.T) { suffix := "MarkedEnforced" @@ -843,17 +882,17 @@ func newDenyAllCstr(suffix string) *unstructured.Unstructured { return cstr } -// func newDenyAllCstrWithLabel(suffix string, labels map[string]string) *unstructured.Unstructured { -// cstr := &unstructured.Unstructured{} -// cstr.SetGroupVersionKind(schema.GroupVersionKind{ -// Group: "constraints.gatekeeper.sh", -// Version: "v1beta1", -// Kind: DenyAll + suffix, -// }) -// cstr.SetName("denyallconstraintforvapbinding") -// cstr.SetLabels(labels) -// return cstr -// } +func newDenyAllCstrWithLabel(suffix string, labels map[string]string) *unstructured.Unstructured { + cstr := &unstructured.Unstructured{} + cstr.SetGroupVersionKind(schema.GroupVersionKind{ + Group: "constraints.gatekeeper.sh", + Version: "v1beta1", + Kind: DenyAll + suffix, + }) + cstr.SetName(denyall + strings.ToLower(suffix)) + cstr.SetLabels(labels) + return cstr +} func getCTByPodStatus(templ *v1beta1.ConstraintTemplate) (v1beta1.ByPodStatus, bool) { statuses := templ.Status.ByPod