Skip to content

Commit

Permalink
Add integration tests for policy controller
Browse files Browse the repository at this point in the history
  • Loading branch information
ChunyiLyu committed Apr 14, 2021
1 parent db998f1 commit b1fe477
Showing 1 changed file with 222 additions and 0 deletions.
222 changes: 222 additions & 0 deletions controllers/policy_controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
package controllers_test

import (
"bytes"
"errors"
"io/ioutil"
"k8s.io/apimachinery/pkg/runtime"
"net/http"
"time"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gstruct"
topology "github.com/rabbitmq/messaging-topology-operator/api/v1alpha2"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)

var _ = Describe("policy-controller", func() {
var policy topology.Policy
var policyName string

JustBeforeEach(func() {
policy = topology.Policy{
ObjectMeta: metav1.ObjectMeta{
Name: policyName,
Namespace: "default",
},
Spec: topology.PolicySpec{
Definition: &runtime.RawExtension{
Raw: []byte(`{"key":"value"}`),
},
RabbitmqClusterReference: topology.RabbitmqClusterReference{
Name: "example-rabbit",
},
},
}
})

Context("creation", func() {
When("the RabbitMQ Client returns a HTTP error response", func() {
BeforeEach(func() {
policyName = "test-http-error"
fakeRabbitMQClient.PutPolicyReturns(&http.Response{
Status: "418 I'm a teapot",
StatusCode: 418,
}, errors.New("a failure"))
})

It("sets the status condition", func() {
Expect(client.Create(ctx, &policy)).To(Succeed())
EventuallyWithOffset(1, func() []topology.Condition {
_ = client.Get(
ctx,
types.NamespacedName{Name: policy.Name, Namespace: policy.Namespace},
&policy,
)

return policy.Status.Conditions
}, 10*time.Second, 1*time.Second).Should(ContainElement(MatchFields(IgnoreExtras, Fields{
"Type": Equal(topology.ConditionType("Ready")),
"Reason": Equal("FailedCreateOrUpdate"),
"Status": Equal(corev1.ConditionFalse),
"Message": ContainSubstring("a failure"),
})))
})
})

When("the RabbitMQ Client returns a Go error response", func() {
BeforeEach(func() {
policyName = "test-go-error"
fakeRabbitMQClient.PutPolicyReturns(nil, errors.New("a go failure"))
})

It("sets the status condition to indicate a failure to reconcile", func() {
Expect(client.Create(ctx, &policy)).To(Succeed())
EventuallyWithOffset(1, func() []topology.Condition {
_ = client.Get(
ctx,
types.NamespacedName{Name: policy.Name, Namespace: policy.Namespace},
&policy,
)

return policy.Status.Conditions
}, 10*time.Second, 1*time.Second).Should(ContainElement(MatchFields(IgnoreExtras, Fields{
"Type": Equal(topology.ConditionType("Ready")),
"Reason": Equal("FailedCreateOrUpdate"),
"Status": Equal(corev1.ConditionFalse),
"Message": ContainSubstring("a go failure"),
})))
})
})

When("success", func() {
BeforeEach(func() {
policyName = "test-create-success"
fakeRabbitMQClient.PutPolicyReturns(&http.Response{
Status: "201 Created",
StatusCode: http.StatusCreated,
}, nil)
})

It("sets the status condition 'Ready' to 'true' ", func() {
Expect(client.Create(ctx, &policy)).To(Succeed())
EventuallyWithOffset(1, func() []topology.Condition {
_ = client.Get(
ctx,
types.NamespacedName{Name: policy.Name, Namespace: policy.Namespace},
&policy,
)

return policy.Status.Conditions
}, 10*time.Second, 1*time.Second).Should(ContainElement(MatchFields(IgnoreExtras, Fields{
"Type": Equal(topology.ConditionType("Ready")),
"Reason": Equal("SuccessfulCreateOrUpdate"),
"Status": Equal(corev1.ConditionTrue),
})))
})
})
})

Context("deletion", func() {
JustBeforeEach(func() {
fakeRabbitMQClient.PutPolicyReturns(&http.Response{
Status: "201 Created",
StatusCode: http.StatusCreated,
}, nil)
Expect(client.Create(ctx, &policy)).To(Succeed())
EventuallyWithOffset(1, func() []topology.Condition {
_ = client.Get(
ctx,
types.NamespacedName{Name: policy.Name, Namespace: policy.Namespace},
&policy,
)

return policy.Status.Conditions
}, 10*time.Second, 1*time.Second).Should(ContainElement(MatchFields(IgnoreExtras, Fields{
"Type": Equal(topology.ConditionType("Ready")),
"Reason": Equal("SuccessfulCreateOrUpdate"),
"Status": Equal(corev1.ConditionTrue),
})))
})

When("the RabbitMQ Client returns a HTTP error response", func() {
BeforeEach(func() {
policyName = "delete-policy-http-error"
fakeRabbitMQClient.DeletePolicyReturns(&http.Response{
Status: "502 Bad Gateway",
StatusCode: http.StatusBadGateway,
Body: ioutil.NopCloser(bytes.NewBufferString("Hello World")),
}, nil)
})

It("publishes a 'warning' event", func() {
Expect(client.Delete(ctx, &policy)).To(Succeed())
Consistently(func() bool {
err := client.Get(ctx, types.NamespacedName{Name: policy.Name, Namespace: policy.Namespace}, &topology.Policy{})
return apierrors.IsNotFound(err)
}, 5).Should(BeFalse())
Expect(observedEvents()).To(ContainElement("Warning FailedDelete failed to delete policy"))
})
})

When("the RabbitMQ Client returns a Go error response", func() {
BeforeEach(func() {
policyName = "delete-go-error"
fakeRabbitMQClient.DeletePolicyReturns(nil, errors.New("some error"))
})

It("publishes a 'warning' event", func() {
Expect(client.Delete(ctx, &policy)).To(Succeed())
Consistently(func() bool {
err := client.Get(ctx, types.NamespacedName{Name: policy.Name, Namespace: policy.Namespace}, &topology.Policy{})
return apierrors.IsNotFound(err)
}, 5).Should(BeFalse())
Expect(observedEvents()).To(ContainElement("Warning FailedDelete failed to delete policy"))
})
})

When("the RabbitMQ cluster is nil", func() {
BeforeEach(func() {
policyName = "delete-client-not-found-error"
})

JustBeforeEach(func() {
prepareNoSuchClusterError()
})

It("successfully deletes the policy regardless", func() {
Expect(client.Delete(ctx, &policy)).To(Succeed())
Eventually(func() bool {
err := client.Get(ctx, types.NamespacedName{Name: policy.Name, Namespace: policy.Namespace}, &topology.Policy{})
return apierrors.IsNotFound(err)
}, 5).Should(BeTrue())
Expect(observedEvents()).To(ContainElement("Normal SuccessfulDelete successfully deleted policy"))
})
})

When("the RabbitMQ Client successfully deletes a policy", func() {
BeforeEach(func() {
policyName = "delete-policy-success"
fakeRabbitMQClient.DeletePolicyReturns(&http.Response{
Status: "204 No Content",
StatusCode: http.StatusNoContent,
}, nil)
})

It("publishes a normal event", func() {
Expect(client.Delete(ctx, &policy)).To(Succeed())
Eventually(func() bool {
err := client.Get(ctx, types.NamespacedName{Name: policy.Name, Namespace: policy.Namespace}, &topology.Policy{})
return apierrors.IsNotFound(err)
}, 5).Should(BeTrue())
observedEvents := observedEvents()
Expect(observedEvents).NotTo(ContainElement("Warning FailedDelete failed to delete policy"))
Expect(observedEvents).To(ContainElement("Normal SuccessfulDelete successfully deleted policy"))
})
})
})
})

0 comments on commit b1fe477

Please sign in to comment.