diff --git a/e2e/additional_role_bindings_test.go b/e2e/additional_role_bindings_test.go index 12578b74..5b548870 100644 --- a/e2e/additional_role_bindings_test.go +++ b/e2e/additional_role_bindings_test.go @@ -30,7 +30,7 @@ import ( "github.com/clastix/capsule/api/v1alpha1" ) -var _ = Describe("creating a Namespace with additional Role Binding", func() { +var _ = Describe("creating a Namespace with an additional Role Binding", func() { tnt := &v1alpha1.Tenant{ ObjectMeta: metav1.ObjectMeta{ Name: "additional-role-binding", @@ -54,6 +54,7 @@ var _ = Describe("creating a Namespace with additional Role Binding", func() { }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { tnt.ResourceVersion = "" @@ -63,7 +64,8 @@ var _ = Describe("creating a Namespace with additional Role Binding", func() { JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) - It("should be assigned on each Namespace", func() { + + It("should be assigned to each Namespace", func() { for _, ns := range []string{"rb-1", "rb-2", "rb-3"} { ns := NewNamespace(ns) NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) diff --git a/e2e/allowed_external_ips_test.go b/e2e/allowed_external_ips_test.go index e878219c..9fb9423e 100644 --- a/e2e/allowed_external_ips_test.go +++ b/e2e/allowed_external_ips_test.go @@ -30,7 +30,7 @@ import ( "github.com/clastix/capsule/api/v1alpha1" ) -var _ = Describe("enforcing an allowed set of Service External IPs", func() { +var _ = Describe("enforcing an allowed set of Service external IPs", func() { tnt := &v1alpha1.Tenant{ ObjectMeta: metav1.ObjectMeta{ Name: "allowed-external-ip", @@ -48,14 +48,17 @@ var _ = Describe("enforcing an allowed set of Service External IPs", func() { }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { - return k8sClient.Create(context.TODO(), tnt.DeepCopy()) + tnt.ResourceVersion = "" + return k8sClient.Create(context.TODO(), tnt) }).Should(Succeed()) }) JustAfterEach(func() { - Expect(k8sClient.Delete(context.TODO(), tnt.DeepCopy())).Should(Succeed()) + Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) + It("should fail creating an evil service", func() { ns := NewNamespace("evil-service") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) @@ -88,6 +91,7 @@ var _ = Describe("enforcing an allowed set of Service External IPs", func() { return err }).ShouldNot(Succeed()) }) + It("should allow the first CIDR block", func() { ns := NewNamespace("allowed-service-cidr") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) diff --git a/e2e/container_registry_test.go b/e2e/container_registry_test.go index c2536d6c..155b44eb 100644 --- a/e2e/container_registry_test.go +++ b/e2e/container_registry_test.go @@ -33,7 +33,7 @@ import ( var _ = Describe("enforcing a Container Registry", func() { tnt := &v1alpha1.Tenant{ ObjectMeta: metav1.ObjectMeta{ - Name: "additional-role-binding", + Name: "container-registry", }, Spec: v1alpha1.TenantSpec{ Owner: v1alpha1.OwnerSpec{ @@ -44,51 +44,36 @@ var _ = Describe("enforcing a Container Registry", func() { Allowed: []string{"docker.io", "docker.tld"}, AllowedRegex: `quay\.\w+`, }, - NamespacesMetadata: v1alpha1.AdditionalMetadata{}, - ServicesMetadata: v1alpha1.AdditionalMetadata{}, - StorageClasses: &v1alpha1.StorageClassesSpec{}, - IngressClasses: &v1alpha1.IngressClassesSpec{}, - LimitRanges: []corev1.LimitRangeSpec{}, - NodeSelector: map[string]string{}, - ResourceQuota: []corev1.ResourceQuotaSpec{}, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { - return k8sClient.Create(context.TODO(), tnt.DeepCopy()) + tnt.ResourceVersion = "" + return k8sClient.Create(context.TODO(), tnt) }).Should(Succeed()) }) JustAfterEach(func() { - Expect(k8sClient.Delete(context.TODO(), tnt.DeepCopy())).Should(Succeed()) + Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) + It("should add labels to Namespace", func() { ns := NewNamespace("registry-labels") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) - - Eventually(func() bool { - if err := k8sClient.Get(context.Background(), types.NamespacedName{Name: ns.Name}, ns); err != nil { - return false + Eventually(func() (ok bool) { + Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: ns.Name}, ns)).Should(Succeed()) + ok, _ = HaveKeyWithValue("capsule.clastix.io/allowed-registries", "docker.io,docker.tld").Match(ns.Annotations) + if !ok { + return } - - for a, expected := range map[string]string{ - "capsule.clastix.io/allowed-registries": "docker.io,docker.tld", - "capsule.clastix.io/allowed-registries-regexp": `quay\.\w+`, - } { - var v string - var ok bool - - v, ok = ns.Annotations[a] - if !ok { - return false - } - if ok = v == expected; !ok { - return false - } + ok, _ = HaveKeyWithValue("capsule.clastix.io/allowed-registries-regexp", `quay\.\w+`).Match(ns.Annotations) + if !ok { + return } - return true }, defaultTimeoutInterval, defaultPollInterval).Should(BeTrue()) }) + It("should deny running a gcr.io container", func() { ns := NewNamespace("registry-deny") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) @@ -110,7 +95,8 @@ var _ = Describe("enforcing a Container Registry", func() { _, err := cs.CoreV1().Pods(ns.Name).Create(context.Background(), pod, metav1.CreateOptions{}) Expect(err).ShouldNot(Succeed()) }) - It("should allow using an item in the list", func() { + + It("should allow using an exact match", func() { ns := NewNamespace("registry-list") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) @@ -134,7 +120,8 @@ var _ = Describe("enforcing a Container Registry", func() { return err }).Should(Succeed()) }) - It("should allow using a registry from regex", func() { + + It("should allow using a regex match", func() { ns := NewNamespace("registry-regex") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) diff --git a/e2e/custom_capsule_group_test.go b/e2e/custom_capsule_group_test.go index 01c7181a..63592099 100644 --- a/e2e/custom_capsule_group_test.go +++ b/e2e/custom_capsule_group_test.go @@ -40,6 +40,7 @@ var _ = Describe("creating a Namespace as Tenant owner with custom --capsule-gro }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { tnt.ResourceVersion = "" @@ -49,19 +50,20 @@ var _ = Describe("creating a Namespace as Tenant owner with custom --capsule-gro JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) - It("should fail", func() { + + It("should fail using a User non matching the capsule-user-group flag", func() { args := append(defaulManagerPodArgs, []string{"--capsule-user-group=test"}...) ModifyCapsuleManagerPodArgs(args) CapsuleClusterGroupParam(podRecreationTimeoutInterval).Should(BeIdenticalTo("test")) ns := NewNamespace("cg-namespace-fail") NamespaceCreation(ns, tnt, podRecreationTimeoutInterval).ShouldNot(Succeed()) }) + It("should succeed and be available in Tenant namespaces list", func() { ModifyCapsuleManagerPodArgs(defaulManagerPodArgs) CapsuleClusterGroupParam(podRecreationTimeoutInterval).Should(BeIdenticalTo("capsule.clastix.io")) ns := NewNamespace("cg-namespace") NamespaceCreation(ns, tnt, podRecreationTimeoutInterval).Should(Succeed()) TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) - }) }) diff --git a/e2e/force_tenant_prefix_test.go b/e2e/force_tenant_prefix_test.go index 7524bb03..68030a13 100644 --- a/e2e/force_tenant_prefix_test.go +++ b/e2e/force_tenant_prefix_test.go @@ -51,6 +51,7 @@ var _ = Describe("creating a Namespace with --force-tenant-name flag", func() { }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { t1.ResourceVersion = "" @@ -67,15 +68,18 @@ var _ = Describe("creating a Namespace with --force-tenant-name flag", func() { Expect(k8sClient.Delete(context.TODO(), t2)).Should(Succeed()) ModifyCapsuleManagerPodArgs(defaulManagerPodArgs) }) - It("should fail with missing prefix", func() { + + It("should fail when non using prefix", func() { ns := NewNamespace("awesome") NamespaceCreation(ns, t1, defaultTimeoutInterval).ShouldNot(Succeed()) }) + It("should succeed using prefix", func() { ns := NewNamespace("awesome-namespace") NamespaceCreation(ns, t1, defaultTimeoutInterval).Should(Succeed()) }) - It("should be assigned according closest match", func() { + + It("should succeed and assigned according to closest match", func() { ns1 := NewNamespace("awesome-tenant") ns2 := NewNamespace("awesome-tenant-namespace") diff --git a/e2e/ingress_class_test.go b/e2e/ingress_class_test.go index 97e23cfd..6d6057a5 100644 --- a/e2e/ingress_class_test.go +++ b/e2e/ingress_class_test.go @@ -2,10 +2,13 @@ /* Copyright 2020 Clastix Labs. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -47,6 +50,7 @@ var _ = Describe("when Tenant handles Ingress classes", func() { }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { tnt.ResourceVersion = "" @@ -56,14 +60,15 @@ var _ = Describe("when Tenant handles Ingress classes", func() { JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) - It("should block non allowed Ingress class", func() { + + It("should block a non allowed class", func() { ns := NewNamespace("ingress-class-disallowed") cs := ownerClient(tnt) NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) - By("non-specifying the class", func() { + By("non-specifying at all", func() { Eventually(func() (err error) { i := &extensionsv1beta1.Ingress{ ObjectMeta: metav1.ObjectMeta{ @@ -80,7 +85,7 @@ var _ = Describe("when Tenant handles Ingress classes", func() { return }, defaultTimeoutInterval, defaultPollInterval).ShouldNot(Succeed()) }) - By("using a forbidden class as Annotation", func() { + By("defining as deprecated annotation", func() { Eventually(func() (err error) { i := &extensionsv1beta1.Ingress{ ObjectMeta: metav1.ObjectMeta{ @@ -100,7 +105,7 @@ var _ = Describe("when Tenant handles Ingress classes", func() { return }, defaultTimeoutInterval, defaultPollInterval).ShouldNot(Succeed()) }) - By("specifying a forbidden class", func() { + By("using the ingressClassName", func() { Eventually(func() (err error) { i := &extensionsv1beta1.Ingress{ ObjectMeta: metav1.ObjectMeta{ @@ -119,7 +124,8 @@ var _ = Describe("when Tenant handles Ingress classes", func() { }, defaultTimeoutInterval, defaultPollInterval).ShouldNot(Succeed()) }) }) - It("should allow enabled Ingress class using the deprecated Annotation", func() { + + It("should allow enabled class using the deprecated annotation", func() { ns := NewNamespace("ingress-class-allowed-annotation") cs := ownerClient(tnt) @@ -147,7 +153,8 @@ var _ = Describe("when Tenant handles Ingress classes", func() { }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) } }) - It("should allow enabled Ingress class using the IngressClassName field", func() { + + It("should allow enabled class using the ingressClassName field", func() { ns := NewNamespace("ingress-class-allowed-annotation") cs := ownerClient(tnt) @@ -178,7 +185,8 @@ var _ = Describe("when Tenant handles Ingress classes", func() { }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) } }) - It("should allow enabled Ingress class regexp using the deprecated Annotation", func() { + + It("should allow enabled Ingress by regex using the deprecated annotation", func() { ns := NewNamespace("ingress-class-allowed-annotation") cs := ownerClient(tnt) ingressClass := "oil-ingress" @@ -205,7 +213,8 @@ var _ = Describe("when Tenant handles Ingress classes", func() { return }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) }) - It("should allow enabled Ingress class regexp using the IngressClassName field", func() { + + It("should allow enabled Ingress by regex using the ingressClassName field", func() { ns := NewNamespace("ingress-class-allowed-annotation") cs := ownerClient(tnt) ingressClass := "oil-haproxy" diff --git a/e2e/missing_tenant_test.go b/e2e/missing_tenant_test.go index 836e387e..ac03eb84 100644 --- a/e2e/missing_tenant_test.go +++ b/e2e/missing_tenant_test.go @@ -28,7 +28,7 @@ import ( "github.com/clastix/capsule/api/v1alpha1" ) -var _ = Describe("Namespace creation with no Tenant assigned", func() { +var _ = Describe("creating a Namespace creation with no Tenant assigned", func() { It("should fail", func() { tnt := &v1alpha1.Tenant{ Spec: v1alpha1.TenantSpec{ diff --git a/e2e/namespace_capsule_label_test.go b/e2e/namespace_capsule_label_test.go index 5b9eb4e4..8e42dcb5 100644 --- a/e2e/namespace_capsule_label_test.go +++ b/e2e/namespace_capsule_label_test.go @@ -42,14 +42,17 @@ var _ = Describe("creating several Namespaces for a Tenant", func() { }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { - return k8sClient.Create(context.TODO(), tnt.DeepCopy()) + tnt.ResourceVersion = "" + return k8sClient.Create(context.TODO(), tnt) }).Should(Succeed()) }) JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) + It("should contains the default Capsule label", func() { namespaces := []*v1.Namespace{ NewNamespace("first-capsule-ns"), @@ -58,10 +61,11 @@ var _ = Describe("creating several Namespaces for a Tenant", func() { } for _, ns := range namespaces { NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) - TenantNamespaceList(tnt, defaultTimeoutInterval).Should(ContainElement(ns.GetName())) - - Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: ns.GetName()}, ns)).Should(Succeed()) - Expect(ns.Labels).Should(HaveKeyWithValue("capsule.clastix.io/tenant", tnt.Name)) + Eventually(func() (ok bool) { + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: ns.GetName()}, ns)).Should(Succeed()) + ok, _ = HaveKeyWithValue("capsule.clastix.io/tenant", tnt.Name).Match(ns.Labels) + return + }, defaultTimeoutInterval, defaultPollInterval).Should(BeTrue()) } }) }) diff --git a/e2e/namespace_metadata_test.go b/e2e/namespace_metadata_test.go index 3e43f233..9ad74399 100644 --- a/e2e/namespace_metadata_test.go +++ b/e2e/namespace_metadata_test.go @@ -51,6 +51,7 @@ var _ = Describe("creating a Namespace for a Tenant with additional metadata", f }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), tnt) @@ -59,21 +60,33 @@ var _ = Describe("creating a Namespace for a Tenant with additional metadata", f JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) - It("should contains additional Namespace metadata", func() { + + It("should contain additional Namespace metadata", func() { ns := NewNamespace("namespace-metadata") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) - Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: ns.GetName()}, ns)).Should(Succeed()) By("checking additional labels", func() { - for _, l := range tnt.Spec.NamespacesMetadata.AdditionalLabels { - Expect(ns.Labels).Should(ContainElement(l)) - } + Eventually(func() (ok bool) { + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: ns.GetName()}, ns)).Should(Succeed()) + for k, v := range tnt.Spec.NamespacesMetadata.AdditionalLabels { + if ok = Expect(ns.Labels).Should(HaveKeyWithValue(k, v)); !ok { + return + } + } + return + }, defaultTimeoutInterval, defaultPollInterval).Should(BeTrue()) }) By("checking additional annotations", func() { - for _, a := range tnt.Spec.NamespacesMetadata.AdditionalAnnotations { - Expect(ns.Annotations).Should(ContainElement(a)) - } + Eventually(func() (ok bool) { + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: ns.GetName()}, ns)).Should(Succeed()) + for k, v := range tnt.Spec.NamespacesMetadata.AdditionalAnnotations { + if ok = Expect(ns.Annotations).Should(HaveKeyWithValue(k, v)); !ok { + return + } + } + return + }, defaultTimeoutInterval, defaultPollInterval).Should(BeTrue()) }) }) }) diff --git a/e2e/new_namespace_test.go b/e2e/new_namespace_test.go index b446bd29..a833f783 100644 --- a/e2e/new_namespace_test.go +++ b/e2e/new_namespace_test.go @@ -40,6 +40,7 @@ var _ = Describe("creating a Namespace as Tenant owner", func() { }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), tnt) @@ -48,6 +49,7 @@ var _ = Describe("creating a Namespace as Tenant owner", func() { JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) + It("should be available in Tenant namespaces list", func() { ns := NewNamespace("new-namespace") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) diff --git a/e2e/overquota_namespace_test.go b/e2e/overquota_namespace_test.go index d8956882..766eeba4 100644 --- a/e2e/overquota_namespace_test.go +++ b/e2e/overquota_namespace_test.go @@ -29,7 +29,7 @@ import ( "github.com/clastix/capsule/api/v1alpha1" ) -var _ = Describe("creating a Namespace over-quota", func() { +var _ = Describe("creating a Namespace in over-quota of three", func() { tnt := &v1alpha1.Tenant{ ObjectMeta: metav1.ObjectMeta{ Name: "over-quota-tenant", @@ -42,6 +42,7 @@ var _ = Describe("creating a Namespace over-quota", func() { NamespaceQuota: pointer.Int32Ptr(3), }, } + JustBeforeEach(func() { EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), tnt) @@ -50,6 +51,7 @@ var _ = Describe("creating a Namespace over-quota", func() { JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) + It("should fail", func() { By("creating three Namespaces", func() { for _, name := range []string{"bob-dev", "bob-staging", "bob-production"} { diff --git a/e2e/owner_webhooks_test.go b/e2e/owner_webhooks_test.go index bb0e9342..fe670ced 100644 --- a/e2e/owner_webhooks_test.go +++ b/e2e/owner_webhooks_test.go @@ -104,6 +104,7 @@ var _ = Describe("when Tenant owner interacts with the webhooks", func() { JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) + It("should disallow deletions", func() { By("blocking Capsule Limit ranges", func() { ns := NewNamespace("limit-range-disallow") @@ -133,7 +134,7 @@ var _ = Describe("when Tenant owner interacts with the webhooks", func() { cs := ownerClient(tnt) Expect(cs.NetworkingV1().NetworkPolicies(ns.GetName()).Delete(context.TODO(), np.Name, metav1.DeleteOptions{})).ShouldNot(Succeed()) }) - By("blocking blocking Capsule Resource Quota", func() { + By("blocking Capsule Resource Quota", func() { ns := NewNamespace("resource-quota-disallow") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) @@ -148,8 +149,9 @@ var _ = Describe("when Tenant owner interacts with the webhooks", func() { Expect(cs.NetworkingV1().NetworkPolicies(ns.GetName()).Delete(context.TODO(), rq.Name, metav1.DeleteOptions{})).ShouldNot(Succeed()) }) }) - It("should allow listing", func() { - By("Limit Range resources", func() { + + It("should allow", func() { + By("listing Limit Range", func() { ns := NewNamespace("limit-range-list") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) @@ -160,7 +162,7 @@ var _ = Describe("when Tenant owner interacts with the webhooks", func() { return }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) }) - By("Network Policy resources", func() { + By("listing Network Policy", func() { ns := NewNamespace("network-policy-list") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) @@ -171,7 +173,7 @@ var _ = Describe("when Tenant owner interacts with the webhooks", func() { return }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) }) - By("Resource Quota resources", func() { + By("listin Resource Quota", func() { ns := NewNamespace("resource-quota-list") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) @@ -183,7 +185,8 @@ var _ = Describe("when Tenant owner interacts with the webhooks", func() { }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) }) }) - It("should allow all actions to Tenant owner Network Policy resources", func() { + + It("should allow all actions to Tenant owner Network Policy", func() { ns := NewNamespace("network-policy-allow") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) diff --git a/e2e/protected_namespace_regex_test.go b/e2e/protected_namespace_regex_test.go index cf52586d..567ef91f 100644 --- a/e2e/protected_namespace_regex_test.go +++ b/e2e/protected_namespace_regex_test.go @@ -40,6 +40,7 @@ var _ = Describe("creating a Namespace with --protected-namespace-regex enabled" }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { tnt.ResourceVersion = "" @@ -49,6 +50,7 @@ var _ = Describe("creating a Namespace with --protected-namespace-regex enabled" JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) + It("should succeed and be available in Tenant namespaces list", func() { args := append(defaulManagerPodArgs, []string{"--protected-namespace-regex=^.*[-.]system$"}...) ModifyCapsuleManagerPodArgs(args) @@ -56,7 +58,8 @@ var _ = Describe("creating a Namespace with --protected-namespace-regex enabled" NamespaceCreation(ns, tnt, podRecreationTimeoutInterval).Should(Succeed()) TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) }) - It("should fail", func() { + + It("should fail using a value non matching the regex", func() { ns := NewNamespace("test-system") NamespaceCreation(ns, tnt, podRecreationTimeoutInterval).ShouldNot(Succeed()) ModifyCapsuleManagerPodArgs(defaulManagerPodArgs) diff --git a/e2e/resource_quota_exceeded_test.go b/e2e/resource_quota_exceeded_test.go index 5aefd589..99f2232b 100644 --- a/e2e/resource_quota_exceeded_test.go +++ b/e2e/resource_quota_exceeded_test.go @@ -21,7 +21,6 @@ package e2e import ( "context" "fmt" - "time" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -35,7 +34,7 @@ import ( "github.com/clastix/capsule/api/v1alpha1" ) -var _ = Describe("exceeding Tenant resource quota", func() { +var _ = Describe("exceeding a Tenant resource quota", func() { tnt := &v1alpha1.Tenant{ ObjectMeta: metav1.ObjectMeta{ Name: "tenant-resources-changes", @@ -115,6 +114,7 @@ var _ = Describe("exceeding Tenant resource quota", func() { }, }, } + nsl := []string{"easy", "peasy"} JustBeforeEach(func() { EventuallyCreation(func() error { @@ -132,7 +132,8 @@ var _ = Describe("exceeding Tenant resource quota", func() { JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) - It("should block new Pods if limit is reached", func() { + + It("should block new Pods", func() { cs := ownerClient(tnt) for _, namespace := range nsl { Eventually(func() (err error) { @@ -166,7 +167,7 @@ var _ = Describe("exceeding Tenant resource quota", func() { } _, err = cs.AppsV1().Deployments(namespace).Create(context.TODO(), d, metav1.CreateOptions{}) return - }, 15*time.Second, time.Second).Should(Succeed()) + }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) } for _, ns := range nsl { n := fmt.Sprintf("capsule-%s-1", tnt.GetName()) @@ -174,55 +175,33 @@ var _ = Describe("exceeding Tenant resource quota", func() { By("retrieving the Resource Quota", func() { Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{Name: n, Namespace: ns}, rq) - }, 15*time.Second, time.Second).Should(Succeed()) + }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) }) By("ensuring the status has been blocked with actual usage", func() { Eventually(func() corev1.ResourceList { _ = k8sClient.Get(context.TODO(), types.NamespacedName{Name: n, Namespace: ns}, rq) return rq.Status.Hard - }, 15*time.Second, time.Second).Should(Equal(rq.Status.Used)) + }, defaultTimeoutInterval, defaultPollInterval).Should(Equal(rq.Status.Used)) }) By("creating an exceeded Pod", func() { - d := &v1.Deployment{ + pod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: "my-exceeded", + Name: "container", }, - Spec: v1.DeploymentSpec{ - Replicas: pointer.Int32Ptr(5), - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app": "exceeded", - }, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app": "exceeded", - }, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "my-exceeded", - Image: "gcr.io/google_containers/pause-amd64:3.0", - }, - }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "container", + Image: "quay.io/google-containers/pause-amd64:3.0", }, }, }, } - _, err := cs.AppsV1().Deployments(ns).Create(context.TODO(), d, metav1.CreateOptions{}) - Expect(err).Should(Succeed()) - Eventually(func() (condition *v1.DeploymentCondition) { - Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: d.GetName(), Namespace: ns}, d)).Should(Succeed()) - for _, i := range d.Status.Conditions { - if i.Type == v1.DeploymentReplicaFailure { - condition = &i - break - } - } - return - }, 30*time.Second, time.Second).ShouldNot(BeNil()) + cs := ownerClient(tnt) + EventuallyCreation(func() error { + _, err := cs.CoreV1().Pods(ns).Create(context.Background(), pod, metav1.CreateOptions{}) + return err + }).ShouldNot(Succeed()) }) } }) diff --git a/e2e/selecting_non_owned_tenant_test.go b/e2e/selecting_non_owned_tenant_test.go index 3cfed261..49a1d462 100644 --- a/e2e/selecting_non_owned_tenant_test.go +++ b/e2e/selecting_non_owned_tenant_test.go @@ -41,6 +41,7 @@ var _ = Describe("creating a Namespace trying to select a third Tenant", func() }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), tnt) @@ -49,6 +50,7 @@ var _ = Describe("creating a Namespace trying to select a third Tenant", func() JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) + It("should fail", func() { var ns *corev1.Namespace @@ -64,6 +66,6 @@ var _ = Describe("creating a Namespace trying to select a third Tenant", func() cs := ownerClient(&v1alpha1.Tenant{Spec: v1alpha1.TenantSpec{Owner: v1alpha1.OwnerSpec{Name: "dale", Kind: "User"}}}) _, err := cs.CoreV1().Namespaces().Create(context.TODO(), ns, metav1.CreateOptions{}) - Expect(err).ShouldNot(Succeed()) + Expect(err).To(HaveOccurred()) }) }) diff --git a/e2e/selecting_tenant_fail_test.go b/e2e/selecting_tenant_fail_test.go index a8993c8c..e9ca49d9 100644 --- a/e2e/selecting_tenant_fail_test.go +++ b/e2e/selecting_tenant_fail_test.go @@ -73,19 +73,20 @@ var _ = Describe("creating a Namespace without a Tenant selector when user owns }, }, } + It("should fail", func() { ns := NewNamespace("fail-ns") By("user owns 2 tenants", func() { - Expect(k8sClient.Create(context.TODO(), t1)).Should(Succeed()) - Expect(k8sClient.Create(context.TODO(), t2)).Should(Succeed()) + EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), t1)}).Should(Succeed()) + EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), t2)}).Should(Succeed()) NamespaceCreation(ns, t1, defaultTimeoutInterval).ShouldNot(Succeed()) NamespaceCreation(ns, t2, defaultTimeoutInterval).ShouldNot(Succeed()) Expect(k8sClient.Delete(context.TODO(), t1)).Should(Succeed()) Expect(k8sClient.Delete(context.TODO(), t2)).Should(Succeed()) }) By("group owns 2 tenants", func() { - Expect(k8sClient.Create(context.TODO(), t3)).Should(Succeed()) - Expect(k8sClient.Create(context.TODO(), t4)).Should(Succeed()) + EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), t3)}).Should(Succeed()) + EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), t4)}).Should(Succeed()) NamespaceCreation(ns, t3, defaultTimeoutInterval).ShouldNot(Succeed()) NamespaceCreation(ns, t4, defaultTimeoutInterval).ShouldNot(Succeed()) Expect(k8sClient.Delete(context.TODO(), t3)).Should(Succeed()) @@ -93,10 +94,10 @@ var _ = Describe("creating a Namespace without a Tenant selector when user owns }) By("user and group owns 4 tenants", func() { t1.ResourceVersion, t2.ResourceVersion, t3.ResourceVersion, t4.ResourceVersion = "", "", "", "" - Expect(k8sClient.Create(context.TODO(), t1)).Should(Succeed()) - Expect(k8sClient.Create(context.TODO(), t2)).Should(Succeed()) - Expect(k8sClient.Create(context.TODO(), t3)).Should(Succeed()) - Expect(k8sClient.Create(context.TODO(), t4)).Should(Succeed()) + EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), t1)}).Should(Succeed()) + EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), t2)}).Should(Succeed()) + EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), t3)}).Should(Succeed()) + EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), t4)}).Should(Succeed()) NamespaceCreation(ns, t1, defaultTimeoutInterval).ShouldNot(Succeed()) NamespaceCreation(ns, t2, defaultTimeoutInterval).ShouldNot(Succeed()) NamespaceCreation(ns, t3, defaultTimeoutInterval).ShouldNot(Succeed()) @@ -107,5 +108,4 @@ var _ = Describe("creating a Namespace without a Tenant selector when user owns Expect(k8sClient.Delete(context.TODO(), t4)).Should(Succeed()) }) }) - }) diff --git a/e2e/selecting_tenant_with_label_test.go b/e2e/selecting_tenant_with_label_test.go index 095e1523..2124c929 100644 --- a/e2e/selecting_tenant_with_label_test.go +++ b/e2e/selecting_tenant_with_label_test.go @@ -51,6 +51,7 @@ var _ = Describe("creating a Namespace with Tenant selector when user owns multi }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { return k8sClient.Create(context.TODO(), t1) @@ -63,6 +64,7 @@ var _ = Describe("creating a Namespace with Tenant selector when user owns multi Expect(k8sClient.Delete(context.TODO(), t1)).Should(Succeed()) Expect(k8sClient.Delete(context.TODO(), t2)).Should(Succeed()) }) + It("should be assigned to the selected Tenant", func() { ns := NewNamespace("tenant-2-ns") By("assigning to the Namespace the Capsule Tenant label", func() { diff --git a/e2e/service_metadata_test.go b/e2e/service_metadata_test.go index ee5ce798..7607c997 100644 --- a/e2e/service_metadata_test.go +++ b/e2e/service_metadata_test.go @@ -2,10 +2,13 @@ /* Copyright 2020 Clastix Labs. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,12 +29,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" - "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/utils/pointer" "github.com/clastix/capsule/api/v1alpha1" ) -var _ = Describe("creating a Service/Endpoint/EndpointSlice for a Tenant with additional metadata", func() { +var _ = Describe("adding metadata to Service objects", func() { tnt := &v1alpha1.Tenant{ ObjectMeta: metav1.ObjectMeta{ Name: "service-metadata", @@ -51,49 +54,40 @@ var _ = Describe("creating a Service/Endpoint/EndpointSlice for a Tenant with ad "clastix.io/custom-annotation": "buzz", }, }, - }, - } - epsCR := &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{ - Name: "epsCR", - Labels: map[string]string{ - "rbac.authorization.k8s.io/aggregate-to-admin": "true", - }, - }, - Rules: []rbacv1.PolicyRule{ - { - APIGroups: []string{"discovery.k8s.io"}, - Resources: []string{"endpointslices"}, - Verbs: []string{"get", "list", "watch", "create", "update", "patch", "delete"}, + AdditionalRoleBindings: []v1alpha1.AdditionalRoleBindings{ + { + ClusterRoleName: "system:controller:endpointslice-controller", + Subjects: []rbacv1.Subject{ + { + Kind: "User", + Name: "gatsby", + }, + }, + }, }, }, } + JustBeforeEach(func() { - Expect(k8sClient.Create(context.TODO(), tnt)).Should(Succeed()) - Expect(k8sClient.Create(context.TODO(), epsCR)).Should(Succeed()) + EventuallyCreation(func() error { + tnt.ResourceVersion = "" + return k8sClient.Create(context.TODO(), tnt) + }).Should(Succeed()) }) JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) - Expect(k8sClient.Delete(context.TODO(), epsCR)).Should(Succeed()) }) - It("service objects should contain additional metadata", func() { - ns := NewNamespace("serivce-metadata") + + It("should apply them to Service", func() { + ns := NewNamespace("service-metadata") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) - meta := metav1.ObjectMeta{ - Name: "test-svc", - Namespace: ns.GetName(), - Labels: map[string]string{ - "k8s.io/custom-label": "wrong", - }, - Annotations: map[string]string{ - "clastix.io/annotation": "baz", - }, - } - svc := &corev1.Service{ - ObjectMeta: meta, + ObjectMeta: metav1.ObjectMeta{ + Name: "service-metadata", + Namespace: ns.GetName(), + }, Spec: corev1.ServiceSpec{ Type: corev1.ServiceTypeClusterIP, Ports: []corev1.ServicePort{ @@ -108,9 +102,46 @@ var _ = Describe("creating a Service/Endpoint/EndpointSlice for a Tenant with ad }, }, } + EventuallyCreation(func() error { + return k8sClient.Create(context.TODO(), svc) + }).Should(Succeed()) + + By("checking additional labels", func() { + Eventually(func() (ok bool) { + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: svc.GetName(), Namespace: ns.GetName()}, svc)).Should(Succeed()) + for k, v := range tnt.Spec.ServicesMetadata.AdditionalLabels { + ok, _ = HaveKeyWithValue(k, v).Match(svc.Labels) + if !ok { + return false + } + } + return true + }, defaultTimeoutInterval, defaultPollInterval).Should(BeTrue()) + }) + By("checking additional annotations", func() { + Eventually(func() (ok bool) { + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: svc.GetName(), Namespace: ns.GetName()}, svc)).Should(Succeed()) + for k, v := range tnt.Spec.ServicesMetadata.AdditionalAnnotations { + ok, _ = HaveKeyWithValue(k, v).Match(svc.Annotations) + if !ok { + return false + } + } + return true + }, defaultTimeoutInterval, defaultPollInterval).Should(BeTrue()) + }) + }) + + It("should apply them to Endpoints", func() { + ns := NewNamespace("endpoints-metadata") + NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) + TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) ep := &corev1.Endpoints{ - ObjectMeta: meta, + ObjectMeta: metav1.ObjectMeta{ + Name: "endpoints-metadata", + Namespace: ns.GetName(), + }, Subsets: []corev1.EndpointSubset{ { Addresses: []corev1.EndpointAddress{ @@ -127,110 +158,91 @@ var _ = Describe("creating a Service/Endpoint/EndpointSlice for a Tenant with ad }, }, } - - cs := ownerClient(tnt) - - Eventually(func() (err error) { - _, err = cs.CoreV1().Services(ns.GetName()).Create(context.TODO(), svc, metav1.CreateOptions{}) - return - }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) - Eventually(func() (err error) { - _, err = cs.CoreV1().Endpoints(ns.GetName()).Create(context.TODO(), ep, metav1.CreateOptions{}) - return - }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) - - By("checking number of labels on service", func() { - Eventually(func() (labelsCnt int) { - k8sClient.Get(context.TODO(), types.NamespacedName{Name: svc.GetName(), Namespace: ns.GetName()}, svc) - return len(svc.GetLabels()) - }, defaultTimeoutInterval, defaultPollInterval).Should(Equal(2)) - }) - By("checking additional labels on service", func() { - for _, l := range tnt.Spec.ServicesMetadata.AdditionalLabels { - Expect(svc.Labels).Should(ContainElement(l)) - } - }) - By("checking number of annotations on service", func() { - Eventually(func() (labelsCnt int) { - k8sClient.Get(context.TODO(), types.NamespacedName{Name: svc.GetName(), Namespace: ns.GetName()}, svc) - return len(svc.GetAnnotations()) - }, defaultTimeoutInterval, defaultPollInterval).Should(Equal(3)) - }) - By("checking additional annotations service", func() { - for _, a := range tnt.Spec.NamespacesMetadata.AdditionalAnnotations { - Expect(svc.Annotations).Should(ContainElement(a)) - } - }) - By("checking number of labels on endpoint", func() { - Eventually(func() (labelsCnt int) { - k8sClient.Get(context.TODO(), types.NamespacedName{Name: ep.GetName(), Namespace: ns.GetName()}, ep) - return len(ep.GetLabels()) - }, defaultTimeoutInterval, defaultPollInterval).Should(Equal(2)) - }) - By("checking additional labels on endpoint", func() { - for _, l := range tnt.Spec.ServicesMetadata.AdditionalLabels { - Expect(ep.Labels).Should(ContainElement(l)) - } - }) - By("checking number of annotations on endpoint", func() { - Eventually(func() (labelsCnt int) { - k8sClient.Get(context.TODO(), types.NamespacedName{Name: ep.GetName(), Namespace: ns.GetName()}, ep) - return len(ep.GetAnnotations()) - }, defaultTimeoutInterval, defaultPollInterval).Should(Equal(3)) - }) - By("checking additional annotations endpoint", func() { - for _, a := range tnt.Spec.NamespacesMetadata.AdditionalAnnotations { - Expect(ep.Annotations).Should(ContainElement(a)) - } - }) - - epsName := "foo" - epsPort := int32(9999) - var eps client.Object - - maj, min, _ := GetKubernetesSemVer() - if maj == 1 && min > 16 { - eps = &discoveryv1beta1.EndpointSlice{ - ObjectMeta: meta, - AddressType: discoveryv1beta1.AddressTypeIPv4, - Endpoints: []discoveryv1beta1.Endpoint{ - { - Addresses: []string{"10.10.1.1"}, - }, - }, - Ports: []discoveryv1beta1.EndpointPort{ - { - Name: &epsName, - Port: &epsPort, - }, - }, - } - Eventually(func() (err error) { - _, err = cs.DiscoveryV1beta1().EndpointSlices(ns.GetName()).Create(context.TODO(), eps.(*discoveryv1beta1.EndpointSlice), metav1.CreateOptions{}) - return - }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) - By("checking number of labels on endpointslice", func() { - Eventually(func() (labelsCnt int) { - k8sClient.Get(context.TODO(), types.NamespacedName{Name: eps.GetName(), Namespace: ns.GetName()}, eps) - return len(eps.GetLabels()) - }, defaultTimeoutInterval, defaultPollInterval).Should(Equal(2)) - }) - By("checking additional annotations endpointslices", func() { - for _, a := range tnt.Spec.NamespacesMetadata.AdditionalAnnotations { - Expect(eps.GetAnnotations()).Should(ContainElement(a)) + EventuallyCreation(func() error { + return k8sClient.Create(context.TODO(), ep) + }).Should(Succeed()) + By("checking additional labels", func() { + Eventually(func() (ok bool) { + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: ep.GetName(), Namespace: ns.GetName()}, ep)).Should(Succeed()) + for k, v := range tnt.Spec.ServicesMetadata.AdditionalLabels { + ok, _ = HaveKeyWithValue(k, v).Match(ep.Labels) + if !ok { + return false + } } - }) - By("checking number of annotations on endpointslice", func() { - Eventually(func() (labelsCnt int) { - k8sClient.Get(context.TODO(), types.NamespacedName{Name: eps.GetName(), Namespace: ns.GetName()}, eps) - return len(eps.GetAnnotations()) - }, defaultTimeoutInterval, defaultPollInterval).Should(Equal(3)) - }) - By("checking additional labels on endpointslices", func() { - for _, l := range tnt.Spec.ServicesMetadata.AdditionalLabels { - Expect(eps.GetLabels()).Should(ContainElement(l)) + return true + }, defaultTimeoutInterval, defaultPollInterval).Should(BeTrue()) + }) + By("checking additional annotations", func() { + Eventually(func() (ok bool) { + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: ep.GetName(), Namespace: ns.GetName()}, ep)).Should(Succeed()) + for k, v := range tnt.Spec.ServicesMetadata.AdditionalAnnotations { + ok, _ = HaveKeyWithValue(k, v).Match(ep.Annotations) + if !ok { + return false + } } - }) + return true + }, defaultTimeoutInterval, defaultPollInterval).Should(BeTrue()) + }) + }) + + It("should apply them to EndpointSlice", func() { + maj, min, v := GetKubernetesSemVer() + if maj == 1 && min <= 16 { + Skip("Running test on Kubernetes " + v + ", doesn't provide EndpointSlice resource") } + + ns := NewNamespace("endpointslice-metadata") + NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) + TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) + + eps := &discoveryv1beta1.EndpointSlice{ + ObjectMeta: metav1.ObjectMeta{ + Name: "endpointslice-metadata", + Namespace: ns.GetName(), + }, + AddressType: discoveryv1beta1.AddressTypeIPv4, + Endpoints: []discoveryv1beta1.Endpoint{ + { + Addresses: []string{"10.10.1.1"}, + }, + }, + Ports: []discoveryv1beta1.EndpointPort{ + { + Name: pointer.StringPtr("foo"), + Port: pointer.Int32Ptr(9999), + }, + }, + } + + EventuallyCreation(func() error { + return k8sClient.Create(context.TODO(), eps) + }).Should(Succeed()) + + By("checking additional annotations EndpointSlice", func() { + Eventually(func() (ok bool) { + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: eps.GetName(), Namespace: ns.GetName()}, eps)).Should(Succeed()) + for k, v := range tnt.Spec.ServicesMetadata.AdditionalAnnotations { + ok, _ = HaveKeyWithValue(k, v).Match(eps.Annotations) + if !ok { + return false + } + } + return true + }, defaultTimeoutInterval, defaultPollInterval).Should(BeTrue()) + }) + By("checking additional labels on EndpointSlice", func() { + Eventually(func() (ok bool) { + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: eps.GetName(), Namespace: ns.GetName()}, eps)).Should(Succeed()) + for k, v := range tnt.Spec.ServicesMetadata.AdditionalLabels { + ok, _ = HaveKeyWithValue(k, v).Match(eps.Labels) + if !ok { + return false + } + } + return true + }, defaultTimeoutInterval, defaultPollInterval).Should(BeTrue()) + }) }) }) diff --git a/e2e/storage_class_test.go b/e2e/storage_class_test.go index 427368b8..c1f98078 100644 --- a/e2e/storage_class_test.go +++ b/e2e/storage_class_test.go @@ -2,10 +2,13 @@ /* Copyright 2020 Clastix Labs. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -47,6 +50,7 @@ var _ = Describe("when Tenant handles Storage classes", func() { }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { tnt.ResourceVersion = "" @@ -56,12 +60,13 @@ var _ = Describe("when Tenant handles Storage classes", func() { JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) - It("should block non allowed Storage Class", func() { + + It("should fails", func() { ns := NewNamespace("storage-class-disallowed") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) - By("non-specifying the class", func() { + By("non-specifying it", func() { Eventually(func() (err error) { cs := ownerClient(tnt) p := &corev1.PersistentVolumeClaim{ @@ -81,7 +86,7 @@ var _ = Describe("when Tenant handles Storage classes", func() { return }, defaultTimeoutInterval, defaultPollInterval).ShouldNot(Succeed()) }) - By("specifying a forbidden class", func() { + By("specifying a forbidden one", func() { Eventually(func() (err error) { cs := ownerClient(tnt) p := &corev1.PersistentVolumeClaim{ @@ -102,13 +107,14 @@ var _ = Describe("when Tenant handles Storage classes", func() { }, defaultTimeoutInterval, defaultPollInterval).ShouldNot(Succeed()) }) }) - It("should allow enabled Storage Class", func() { + + It("should allow", func() { ns := NewNamespace("storage-class-allowed") cs := ownerClient(tnt) NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) TenantNamespaceList(tnt, podRecreationTimeoutInterval).Should(ContainElement(ns.GetName())) - By("using allowed storageClass names", func() { + By("using exact matches", func() { for _, c := range tnt.Spec.StorageClasses.Allowed { Eventually(func() (err error) { p := &corev1.PersistentVolumeClaim{ @@ -130,7 +136,7 @@ var _ = Describe("when Tenant handles Storage classes", func() { }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) } }) - By("using allowed storageClass regexp", func() { + By("using a regex match", func() { allowedClass := "oil-storage" Eventually(func() (err error) { p := &corev1.PersistentVolumeClaim{ @@ -150,7 +156,6 @@ var _ = Describe("when Tenant handles Storage classes", func() { _, err = cs.CoreV1().PersistentVolumeClaims(ns.GetName()).Create(context.TODO(), p, metav1.CreateOptions{}) return }, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) - }) }) }) diff --git a/e2e/tenant_name_webhook_test.go b/e2e/tenant_name_webhook_test.go index d83942c2..fbe856de 100644 --- a/e2e/tenant_name_webhook_test.go +++ b/e2e/tenant_name_webhook_test.go @@ -40,6 +40,7 @@ var _ = Describe("creating a Tenant with wrong name", func() { }, }, } + It("should fail", func() { Expect(k8sClient.Create(context.TODO(), tnt)).ShouldNot(Succeed()) }) diff --git a/e2e/tenant_owner_group_test.go b/e2e/tenant_owner_group_test.go index 28434c39..e236f261 100644 --- a/e2e/tenant_owner_group_test.go +++ b/e2e/tenant_owner_group_test.go @@ -40,6 +40,7 @@ var _ = Describe("creating a Namespace with group Tenant owner", func() { }, }, } + JustBeforeEach(func() { EventuallyCreation(func() error { tnt.ResourceVersion = "" @@ -49,6 +50,7 @@ var _ = Describe("creating a Namespace with group Tenant owner", func() { JustAfterEach(func() { Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed()) }) + It("should succeed and be available in Tenant namespaces list", func() { ns := NewNamespace("gto-namespace") NamespaceCreation(ns, tnt, defaultTimeoutInterval).Should(Succeed()) diff --git a/e2e/tenant_resources_changes_test.go b/e2e/tenant_resources_changes_test.go index 084ae34a..87b0e652 100644 --- a/e2e/tenant_resources_changes_test.go +++ b/e2e/tenant_resources_changes_test.go @@ -180,7 +180,7 @@ var _ = Describe("changing Tenant managed Kubernetes resources", func() { }) It("should reapply the original resources upon third party change", func() { for _, ns := range nsl { - By("changing Limit Range resources", func() { + By("changing Limit Range", func() { for i, s := range tnt.Spec.LimitRanges { n := fmt.Sprintf("capsule-%s-%d", tnt.GetName(), i) lr := &corev1.LimitRange{} @@ -198,7 +198,7 @@ var _ = Describe("changing Tenant managed Kubernetes resources", func() { }, defaultTimeoutInterval, defaultPollInterval).Should(Equal(s)) } }) - By("changing Network Policy resources", func() { + By("changing Network Policy", func() { for i, s := range tnt.Spec.NetworkPolicies { n := fmt.Sprintf("capsule-%s-%d", tnt.GetName(), i) np := &networkingv1.NetworkPolicy{} @@ -218,7 +218,7 @@ var _ = Describe("changing Tenant managed Kubernetes resources", func() { }, defaultTimeoutInterval, defaultPollInterval).Should(Equal(s)) } }) - By("changing Resource Quota resources", func() { + By("changing Resource Quota", func() { for i, s := range tnt.Spec.ResourceQuota { n := fmt.Sprintf("capsule-%s-%d", tnt.GetName(), i) rq := &corev1.ResourceQuota{} diff --git a/e2e/tenant_resources_test.go b/e2e/tenant_resources_test.go index d1886270..e94f9faa 100644 --- a/e2e/tenant_resources_test.go +++ b/e2e/tenant_resources_test.go @@ -180,7 +180,7 @@ var _ = Describe("creating namespaces within a Tenant with resources", func() { }) It("should contains all replicated resources", func() { for _, name := range nsl { - By("checking Limit Range resources", func() { + By("checking Limit Range", func() { for i, s := range tnt.Spec.LimitRanges { n := fmt.Sprintf("capsule-%s-%d", tnt.GetName(), i) lr := &corev1.LimitRange{} @@ -190,7 +190,7 @@ var _ = Describe("creating namespaces within a Tenant with resources", func() { Expect(lr.Spec).Should(Equal(s)) } }) - By("checking Network Policy resources", func() { + By("checking Network Policy", func() { for i, s := range tnt.Spec.NetworkPolicies { n := fmt.Sprintf("capsule-%s-%d", tnt.GetName(), i) np := &networkingv1.NetworkPolicy{} @@ -211,7 +211,7 @@ var _ = Describe("creating namespaces within a Tenant with resources", func() { return ns.GetAnnotations()["scheduler.alpha.kubernetes.io/node-selector"] }, 10*time.Second, time.Second).Should(Equal(strings.Join(selector, ","))) }) - By("checking the Resource Quota resources", func() { + By("checking the Resource Quota", func() { for i, s := range tnt.Spec.ResourceQuota { n := fmt.Sprintf("capsule-%s-%d", tnt.GetName(), i) rq := &corev1.ResourceQuota{}