Skip to content

Commit

Permalink
artemiscloud#155 - Expose Tolerations as part of the Deployment Plan
Browse files Browse the repository at this point in the history
Also tweaked the tests to improve

Also tweaked some logic around creating new crd on changes
  • Loading branch information
andytaylor committed Feb 23, 2022
1 parent ee0c9fa commit acd7841
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 36 deletions.
3 changes: 2 additions & 1 deletion api/v1beta1/activemqartemis_types.go
Expand Up @@ -213,7 +213,8 @@ type DeploymentPlanType struct {
LivenessProbe corev1.Probe `json:"livenessProbe,omitempty"`
ReadinessProbe corev1.Probe `json:"readinessProbe,omitempty"`
// Whether or not to install the artemis metrics plugin
EnableMetricsPlugin *bool `json:"enableMetricsPlugin,omitempty"`
EnableMetricsPlugin *bool `json:"enableMetricsPlugin,omitempty"`
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
}

type PodSecurityType struct {
Expand Down
8 changes: 8 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions config/crd/bases/broker.amq.io_activemqartemises.yaml
Expand Up @@ -863,6 +863,46 @@ spec:
size:
type: string
type: object
tolerations:
items:
description: The pod this Toleration is attached to tolerates
any taint that matches the triple <key,value,effect> using
the matching operator <operator>.
properties:
effect:
description: Effect indicates the taint effect to match.
Empty means match all taint effects. When specified, allowed
values are NoSchedule, PreferNoSchedule and NoExecute.
type: string
key:
description: Key is the taint key that the toleration applies
to. Empty means match all taint keys. If the key is empty,
operator must be Exists; this combination means to match
all values and all keys.
type: string
operator:
description: Operator represents a key's relationship to
the value. Valid operators are Exists and Equal. Defaults
to Equal. Exists is equivalent to wildcard for value,
so that a pod can tolerate all taints of a particular
category.
type: string
tolerationSeconds:
description: TolerationSeconds represents the period of
time the toleration (which must be of effect NoExecute,
otherwise this field is ignored) tolerates the taint.
By default, it is not set, which means tolerate the taint
forever (do not evict). Zero and negative values will
be treated as 0 (evict immediately) by the system.
format: int64
type: integer
value:
description: Value is the taint value the toleration matches
to. If the operator is Exists, the value should be empty,
otherwise just a regular string.
type: string
type: object
type: array
type: object
upgrades:
description: ActiveMQArtemis App product upgrade flags
Expand Down
165 changes: 148 additions & 17 deletions controllers/activemqartemis_controller_test.go
Expand Up @@ -57,6 +57,100 @@ var _ = Describe("artemis controller", func() {
interval = time.Millisecond * 250
)

Context("Tolerations Test", func() {
It("passing in 2 tolerations", func() {
By("Creating a crd with 2 tolerations")
ctx := context.Background()
crd := generateArtemisSpec(namespace)
crd.Spec.DeploymentPlan.Tolerations = []corev1.Toleration{
{
Key: "foo",
Value: "bar",
Effect: "NoSchedule",
},
{
Key: "yes",
Value: "No",
Effect: "NoSchedule",
},
}

By("Deploying the CRD " + crd.ObjectMeta.Name)
Expect(k8sClient.Create(ctx, &crd)).Should(Succeed())

createdCrd := &brokerv1beta1.ActiveMQArtemis{}
createdSs := &appsv1.StatefulSet{}

By("Making sure that the CRD gets deployed " + crd.ObjectMeta.Name)
Eventually(func() bool {
return checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
Expect(createdCrd.Name).Should(Equal(crd.ObjectMeta.Name))
By("Checking that Stateful Set is Created with the tolerations " + namer.CrToSS(createdCrd.Name))
Eventually(func() bool {
key := types.NamespacedName{Name: namer.CrToSS(createdCrd.Name), Namespace: namespace}

err := k8sClient.Get(ctx, key, createdSs)

if err != nil {
return false
}
return len(createdSs.Spec.Template.Spec.Tolerations) == 2
}, timeout, interval).Should(Equal(true))
Expect(len(createdSs.Spec.Template.Spec.Tolerations) == 2).Should(BeTrue())
Expect(createdSs.Spec.Template.Spec.Tolerations[0].Key == "foo").Should(BeTrue())
Expect(createdSs.Spec.Template.Spec.Tolerations[0].Value == "bar").Should(BeTrue())
Expect(createdSs.Spec.Template.Spec.Tolerations[0].Effect == "NoSchedule").Should(BeTrue())
Expect(createdSs.Spec.Template.Spec.Tolerations[1].Key == "yes").Should(BeTrue())
Expect(createdSs.Spec.Template.Spec.Tolerations[1].Value == "No").Should(BeTrue())
Expect(createdSs.Spec.Template.Spec.Tolerations[1].Effect == "NoSchedule").Should(BeTrue())

original := generateOriginalArtemisSpec(namespace, createdCrd.Name)
Eventually(func() bool {
return checkCrdUpTodate(crd.ObjectMeta.Name, namespace, createdCrd, original)
}, timeout, interval).Should(BeTrue())
original.Spec.DeploymentPlan.Tolerations = []corev1.Toleration{
{
Key: "yes",
Value: "No",
Effect: "NoSchedule",
},
}

By("Redeploying the CRD with different Tolerations " + original.Name)
Eventually(func() bool {
err := k8sClient.Update(ctx, original)

if err != nil {
fmt.Printf("Error updating cr: %v\n", err)
return false
}
return true
}, timeout, interval).Should(Equal(true))
By("and checking there is just a single Toleration")
Eventually(func() bool {
key := types.NamespacedName{Name: namer.CrToSS(createdCrd.Name), Namespace: namespace}

err := k8sClient.Get(ctx, key, createdSs)

if err != nil {
return false
}
return len(createdSs.Spec.Template.Spec.Tolerations) == 1
}, timeout, interval).Should(Equal(true))
Expect(len(createdSs.Spec.Template.Spec.Tolerations) == 1).Should(BeTrue())
Expect(createdSs.Spec.Template.Spec.Tolerations[0].Key == "yes").Should(BeTrue())
Expect(createdSs.Spec.Template.Spec.Tolerations[0].Value == "No").Should(BeTrue())
Expect(createdSs.Spec.Template.Spec.Tolerations[0].Effect == "NoSchedule").Should(BeTrue())

By("check it has gone")
Expect(k8sClient.Delete(ctx, createdCrd))
Eventually(func() bool {
return checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
})
})

Context("Liveness Probe Tests", func() {
It("Override Liveness Probe No Exec", func() {
By("By creating a crd with Liveness Probe")
Expand All @@ -78,7 +172,9 @@ var _ = Describe("artemis controller", func() {
Expect(k8sClient.Create(ctx, &crd)).Should(Succeed())

By("Making sure that the CRD gets deployed")
Eventually(checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
Expect(createdCrd.Name).Should(Equal(crd.ObjectMeta.Name))

By("Checking that Stateful Set is Created with the Liveness Probe")
Expand Down Expand Up @@ -115,9 +211,10 @@ var _ = Describe("artemis controller", func() {
}, timeout, interval).Should(Equal(true))

By("Updating the CR")
Eventually(checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
original := generateOriginalArtemisSpec(namespace, createdCrd.Name)

Eventually(func() bool {
return checkCrdUpTodate(crd.ObjectMeta.Name, namespace, createdCrd, original)
}, timeout, interval).Should(BeTrue())
original.Spec.DeploymentPlan.LivenessProbe.PeriodSeconds = 15
original.Spec.DeploymentPlan.LivenessProbe.InitialDelaySeconds = 16
original.Spec.DeploymentPlan.LivenessProbe.TimeoutSeconds = 17
Expand Down Expand Up @@ -152,7 +249,9 @@ var _ = Describe("artemis controller", func() {

By("check it has gone")
Expect(k8sClient.Delete(ctx, createdCrd))
Eventually(checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
})

It("Override Liveness Probe Exec", func() {
Expand All @@ -173,7 +272,9 @@ var _ = Describe("artemis controller", func() {
Expect(k8sClient.Create(ctx, &crd)).Should(Succeed())

By("Making sure that the CRD gets deployed")
Eventually(checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
Expect(createdCrd.Name).Should(Equal(crd.ObjectMeta.Name))

By("Checking that Stateful Set is Created with the Liveness Probe")
Expand All @@ -194,7 +295,9 @@ var _ = Describe("artemis controller", func() {
Expect(k8sClient.Delete(ctx, createdCrd))

By("check it has gone")
Eventually(checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
})

It("Default Liveness Probe", func() {
Expand All @@ -206,7 +309,9 @@ var _ = Describe("artemis controller", func() {
createdCrd := &brokerv1beta1.ActiveMQArtemis{}
createdSs := &appsv1.StatefulSet{}
Expect(k8sClient.Create(ctx, &crd)).Should(Succeed())
Eventually(checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
Expect(createdCrd.Name).Should(Equal(crd.ObjectMeta.Name))

By("Checking that the Liveness Probe is created")
Expand All @@ -226,7 +331,9 @@ var _ = Describe("artemis controller", func() {
Expect(k8sClient.Delete(ctx, createdCrd))

By("check it has gone")
Eventually(checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
})
})

Expand All @@ -250,7 +357,9 @@ var _ = Describe("artemis controller", func() {
Expect(k8sClient.Create(ctx, &crd)).Should(Succeed())

By("Making sure that the CRD gets deployed")
Eventually(checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
Expect(createdCrd.Name).Should(Equal(crd.ObjectMeta.Name))

By("Checking that Stateful Set is Created with the Readiness Probe")
Expand All @@ -273,7 +382,9 @@ var _ = Describe("artemis controller", func() {
Expect(k8sClient.Delete(ctx, createdCrd))

By("check it has gone")
Eventually(checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
})

It("Override Readiness Probe Exec", func() {
Expand All @@ -294,7 +405,9 @@ var _ = Describe("artemis controller", func() {
Expect(k8sClient.Create(ctx, &crd)).Should(Succeed())

By("Making sure that the CRD gets deployed")
Eventually(checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
Expect(createdCrd.Name).Should(Equal(crd.ObjectMeta.Name))

By("Checking that Stateful Set is Created with the Readiness Probe")
Expand All @@ -315,7 +428,9 @@ var _ = Describe("artemis controller", func() {
Expect(k8sClient.Delete(ctx, createdCrd))

By("check it has gone")
Eventually(checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
})

It("Default Readiness Probe", func() {
Expand All @@ -328,7 +443,9 @@ var _ = Describe("artemis controller", func() {
createdSs := &appsv1.StatefulSet{}
Expect(k8sClient.Create(ctx, &crd)).Should(Succeed())

Eventually(checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
Expect(createdCrd.Name).Should(Equal(crd.ObjectMeta.Name))

By("Checking that the Readiness Probe is created")
Expand All @@ -351,7 +468,9 @@ var _ = Describe("artemis controller", func() {
Expect(k8sClient.Delete(ctx, createdCrd))

By("check it has gone")
Eventually(checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
})
})

Expand All @@ -364,7 +483,9 @@ var _ = Describe("artemis controller", func() {

createdCrd := &brokerv1beta1.ActiveMQArtemis{}

Eventually(checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdCreated(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
Expect(createdCrd.Name).Should(Equal(crd.ObjectMeta.Name))

// would like more status updates on createdCrd
Expand Down Expand Up @@ -404,7 +525,9 @@ var _ = Describe("artemis controller", func() {
Expect(k8sClient.Delete(ctx, &crd)).Should(Succeed())

By("check it has gone")
Eventually(checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd), timeout, interval).Should(BeTrue())
Eventually(func() bool {
return checkCrdDeleted(crd.ObjectMeta.Name, namespace, createdCrd)
}, timeout, interval).Should(BeTrue())
})
})

Expand Down Expand Up @@ -516,14 +639,22 @@ func randString() string {
return b.String()
}

func checkCrdUpTodate(name string, nameSpace string, crd *brokerv1beta1.ActiveMQArtemis, original *brokerv1beta1.ActiveMQArtemis) bool {
key := types.NamespacedName{Name: name, Namespace: nameSpace}
err := k8sClient.Get(ctx, key, crd)
originalversion := original.ObjectMeta.ResourceVersion
fmt.Printf("Original Version %v Updated Version %v\n", originalversion, crd.ObjectMeta.ResourceVersion)
original.ObjectMeta.ResourceVersion = crd.ObjectMeta.ResourceVersion
return err == nil && crd.ObjectMeta.ResourceVersion == originalversion
}

func checkCrdCreated(name string, nameSpace string, crd *brokerv1beta1.ActiveMQArtemis) bool {
key := types.NamespacedName{Name: name, Namespace: nameSpace}
err := k8sClient.Get(ctx, key, crd)
return err == nil
}

func checkCrdDeleted(name string, namespace string, crd *brokerv1beta1.ActiveMQArtemis) bool {
//fetched := &pscv1alpha1.PreScaledCronJob{}
err := k8sClient.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, crd)
return errors.IsNotFound(err)
}

0 comments on commit acd7841

Please sign in to comment.