mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-08-19 20:46:42 +00:00
Making tests less flaky (#172)
This commit is contained in:
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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()))
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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"} {
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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())
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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())
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
@@ -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() {
|
||||
|
||||
+148
-136
@@ -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())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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())
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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())
|
||||
})
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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{}
|
||||
|
||||
@@ -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{}
|
||||
|
||||
Reference in New Issue
Block a user