Skip to content

Commit adcb836

Browse files
committed
operator_controller_test: ensure we cleanup after each spec
Signed-off-by: Joe Lanford <[email protected]>
1 parent 3d30ad0 commit adcb836

File tree

2 files changed

+85
-125
lines changed

2 files changed

+85
-125
lines changed

internal/controllers/operator_controller_test.go

+63-125
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ var _ = Describe("Operator Controller Test", func() {
5252
BeforeEach(func() {
5353
opKey = types.NamespacedName{Name: fmt.Sprintf("operator-test-%s", rand.String(8))}
5454
})
55+
AfterEach(func() {
56+
verifyInvariants(ctx, reconciler.Client, operator)
57+
Expect(cl.DeleteAllOf(ctx, &operatorsv1alpha1.Operator{})).To(Succeed())
58+
Expect(cl.DeleteAllOf(ctx, &rukpakv1alpha1.BundleDeployment{})).To(Succeed())
59+
})
5560
When("the operator specifies a non-existent package", func() {
5661
var pkgName string
5762
BeforeEach(func() {
@@ -137,7 +142,6 @@ var _ = Describe("Operator Controller Test", func() {
137142
err := cl.Create(ctx, operator)
138143
Expect(err).NotTo(HaveOccurred())
139144
})
140-
141145
When("the BundleDeployment does not exist", func() {
142146
BeforeEach(func() {
143147
By("running reconcile")
@@ -210,16 +214,16 @@ var _ = Describe("Operator Controller Test", func() {
210214
},
211215
},
212216
}
213-
214217
})
215218

216219
When("the BundleDeployment spec is out of date", func() {
217-
It("results in the expected BundleDeployment", func() {
220+
BeforeEach(func() {
218221
By("modifying the BD spec and creating the object")
219222
bd.Spec.ProvisionerClassName = "core-rukpak-io-helm"
220223
err := cl.Create(ctx, bd)
221224
Expect(err).NotTo(HaveOccurred())
222-
225+
})
226+
It("results in the expected BundleDeployment", func() {
223227
By("running reconcile")
224228
res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey})
225229
Expect(res).To(Equal(ctrl.Result{}))
@@ -508,17 +512,12 @@ var _ = Describe("Operator Controller Test", func() {
508512
})
509513

510514
})
511-
512-
AfterEach(func() {
513-
err := cl.Delete(ctx, bd)
514-
Expect(err).NotTo(HaveOccurred())
515-
})
516-
517515
})
518516
When("an out-of-date BundleDeployment exists", func() {
517+
var bd *rukpakv1alpha1.BundleDeployment
519518
BeforeEach(func() {
520519
By("creating the expected BD")
521-
err := cl.Create(ctx, &rukpakv1alpha1.BundleDeployment{
520+
bd = &rukpakv1alpha1.BundleDeployment{
522521
ObjectMeta: metav1.ObjectMeta{Name: opKey.Name},
523522
Spec: rukpakv1alpha1.BundleDeploymentSpec{
524523
ProvisionerClassName: "foo",
@@ -534,7 +533,8 @@ var _ = Describe("Operator Controller Test", func() {
534533
},
535534
},
536535
},
537-
})
536+
}
537+
err := cl.Create(ctx, bd)
538538
Expect(err).NotTo(HaveOccurred())
539539

540540
By("running reconcile")
@@ -633,12 +633,6 @@ var _ = Describe("Operator Controller Test", func() {
633633
err = cl.Create(ctx, operator)
634634
Expect(err).NotTo(HaveOccurred())
635635
})
636-
637-
AfterEach(func() {
638-
err := cl.Delete(ctx, dupOperator)
639-
Expect(err).NotTo(HaveOccurred())
640-
})
641-
642636
It("sets resolution failure status", func() {
643637
By("running reconcile")
644638
res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey})
@@ -665,51 +659,6 @@ var _ = Describe("Operator Controller Test", func() {
665659
Expect(cond.Message).To(Equal("installation has not been attempted as resolution failed"))
666660
})
667661
})
668-
When("the existing operator status is based on bundleDeployment", func() {
669-
const pkgName = "prometheus"
670-
var (
671-
bd *rukpakv1alpha1.BundleDeployment
672-
)
673-
BeforeEach(func() {
674-
By("creating the expected BundleDeployment")
675-
bd = &rukpakv1alpha1.BundleDeployment{
676-
ObjectMeta: metav1.ObjectMeta{Name: opKey.Name},
677-
Spec: rukpakv1alpha1.BundleDeploymentSpec{
678-
ProvisionerClassName: "core-rukpak-io-plain",
679-
Template: &rukpakv1alpha1.BundleTemplate{
680-
Spec: rukpakv1alpha1.BundleSpec{
681-
ProvisionerClassName: "core-rukpak-io-registry",
682-
Source: rukpakv1alpha1.BundleSource{
683-
Type: rukpakv1alpha1.SourceTypeImage,
684-
Image: &rukpakv1alpha1.ImageSource{
685-
Ref: "quay.io/operatorhubio/prometheus@sha256:5b04c49d8d3eff6a338b56ec90bdf491d501fe301c9cdfb740e5bff6769a21ed",
686-
},
687-
},
688-
},
689-
},
690-
},
691-
}
692-
err := cl.Create(ctx, bd)
693-
Expect(err).NotTo(HaveOccurred())
694-
695-
By("creating the operator object")
696-
operator = &operatorsv1alpha1.Operator{
697-
ObjectMeta: metav1.ObjectMeta{Name: opKey.Name},
698-
Spec: operatorsv1alpha1.OperatorSpec{
699-
PackageName: pkgName,
700-
},
701-
}
702-
err = cl.Create(ctx, operator)
703-
Expect(err).NotTo(HaveOccurred())
704-
705-
})
706-
707-
AfterEach(func() {
708-
err := cl.Delete(ctx, bd)
709-
Expect(err).NotTo(HaveOccurred())
710-
})
711-
712-
})
713662
When("the operator specifies a channel with version that exist", func() {
714663
var pkgName string
715664
var pkgVer string
@@ -954,75 +903,64 @@ var _ = Describe("Operator Controller Test", func() {
954903
Expect(cond.Message).To(Equal("installation has not been attempted as resolution failed"))
955904
})
956905
})
957-
AfterEach(func() {
958-
verifyInvariants(ctx, operator)
906+
When("an invalid semver is provided that bypasses the regex validation", func() {
907+
var (
908+
pkgName string
909+
fakeClient client.Client
910+
)
911+
BeforeEach(func() {
912+
opKey = types.NamespacedName{Name: fmt.Sprintf("operator-validation-test-%s", rand.String(8))}
959913

960-
err := cl.Delete(ctx, operator)
961-
Expect(err).To(Not(HaveOccurred()))
962-
})
963-
})
964-
When("an invalid semver is provided that bypasses the regex validation", func() {
965-
var (
966-
operator *operatorsv1alpha1.Operator
967-
opKey types.NamespacedName
968-
pkgName string
969-
fakeClient client.Client
970-
)
971-
BeforeEach(func() {
972-
opKey = types.NamespacedName{Name: fmt.Sprintf("operator-validation-test-%s", rand.String(8))}
973-
974-
By("injecting creating a client with the bad operator CR")
975-
pkgName = fmt.Sprintf("exists-%s", rand.String(6))
976-
operator = &operatorsv1alpha1.Operator{
977-
ObjectMeta: metav1.ObjectMeta{Name: opKey.Name},
978-
Spec: operatorsv1alpha1.OperatorSpec{
979-
PackageName: pkgName,
980-
Version: "1.2.3-123abc_def", // bad semver that matches the regex on the CR validation
981-
},
982-
}
983-
984-
// this bypasses client/server-side CR validation and allows us to test the reconciler's validation
985-
fakeClient = fake.NewClientBuilder().WithScheme(sch).WithObjects(operator).Build()
986-
987-
By("changing the reconciler client to the fake client")
988-
reconciler.Client = fakeClient
989-
})
990-
AfterEach(func() {
991-
By("changing the reconciler client back to the real client")
992-
reconciler.Client = cl
993-
})
914+
By("injecting creating a client with the bad operator CR")
915+
pkgName = fmt.Sprintf("exists-%s", rand.String(6))
916+
operator = &operatorsv1alpha1.Operator{
917+
ObjectMeta: metav1.ObjectMeta{Name: opKey.Name},
918+
Spec: operatorsv1alpha1.OperatorSpec{
919+
PackageName: pkgName,
920+
Version: "1.2.3-123abc_def", // bad semver that matches the regex on the CR validation
921+
},
922+
}
994923

995-
It("should add an invalid spec condition and *not* re-enqueue for reconciliation", func() {
996-
By("running reconcile")
997-
res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey})
998-
Expect(res).To(Equal(ctrl.Result{}))
999-
Expect(err).ToNot(HaveOccurred())
1000-
1001-
By("fetching updated operator after reconcile")
1002-
Expect(fakeClient.Get(ctx, opKey, operator)).NotTo(HaveOccurred())
1003-
1004-
By("Checking the status fields")
1005-
Expect(operator.Status.ResolvedBundleResource).To(Equal(""))
1006-
Expect(operator.Status.InstalledBundleResource).To(Equal(""))
1007-
1008-
By("checking the expected conditions")
1009-
cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeResolved)
1010-
Expect(cond).NotTo(BeNil())
1011-
Expect(cond.Status).To(Equal(metav1.ConditionUnknown))
1012-
Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonResolutionUnknown))
1013-
Expect(cond.Message).To(Equal("validation has not been attempted as spec is invalid"))
1014-
cond = apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeInstalled)
1015-
Expect(cond).NotTo(BeNil())
1016-
Expect(cond.Status).To(Equal(metav1.ConditionUnknown))
1017-
Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonInstallationStatusUnknown))
1018-
Expect(cond.Message).To(Equal("installation has not been attempted as spec is invalid"))
924+
// this bypasses client/server-side CR validation and allows us to test the reconciler's validation
925+
fakeClient = fake.NewClientBuilder().WithScheme(sch).WithObjects(operator).Build()
926+
927+
By("changing the reconciler client to the fake client")
928+
reconciler.Client = fakeClient
929+
})
930+
931+
It("should add an invalid spec condition and *not* re-enqueue for reconciliation", func() {
932+
By("running reconcile")
933+
res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey})
934+
Expect(res).To(Equal(ctrl.Result{}))
935+
Expect(err).ToNot(HaveOccurred())
936+
937+
By("fetching updated operator after reconcile")
938+
Expect(fakeClient.Get(ctx, opKey, operator)).NotTo(HaveOccurred())
939+
940+
By("Checking the status fields")
941+
Expect(operator.Status.ResolvedBundleResource).To(Equal(""))
942+
Expect(operator.Status.InstalledBundleResource).To(Equal(""))
943+
944+
By("checking the expected conditions")
945+
cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeResolved)
946+
Expect(cond).NotTo(BeNil())
947+
Expect(cond.Status).To(Equal(metav1.ConditionUnknown))
948+
Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonResolutionUnknown))
949+
Expect(cond.Message).To(Equal("validation has not been attempted as spec is invalid"))
950+
cond = apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeInstalled)
951+
Expect(cond).NotTo(BeNil())
952+
Expect(cond.Status).To(Equal(metav1.ConditionUnknown))
953+
Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonInstallationStatusUnknown))
954+
Expect(cond.Message).To(Equal("installation has not been attempted as spec is invalid"))
955+
})
1019956
})
957+
1020958
})
1021959
})
1022960

1023-
func verifyInvariants(ctx context.Context, op *operatorsv1alpha1.Operator) {
961+
func verifyInvariants(ctx context.Context, c client.Client, op *operatorsv1alpha1.Operator) {
1024962
key := client.ObjectKeyFromObject(op)
1025-
err := cl.Get(ctx, key, op)
963+
err := c.Get(ctx, key, op)
1026964
Expect(err).To(BeNil())
1027965

1028966
verifyConditionsInvariants(op)

internal/controllers/suite_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ limitations under the License.
1717
package controllers_test
1818

1919
import (
20+
"context"
2021
"path/filepath"
2122
"testing"
2223

2324
. "github.com/onsi/ginkgo/v2"
2425
. "github.com/onsi/gomega"
2526
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"
27+
"k8s.io/apimachinery/pkg/api/meta"
2628
"k8s.io/apimachinery/pkg/runtime"
2729
"k8s.io/client-go/rest"
2830
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -77,7 +79,27 @@ var _ = BeforeSuite(func() {
7779
})
7880

7981
var _ = AfterSuite(func() {
82+
var operators operatorsv1alpha1.OperatorList
83+
var bundleDeployments rukpakv1alpha1.BundleDeploymentList
84+
85+
Expect(cl.List(context.Background(), &operators)).To(Succeed())
86+
Expect(cl.List(context.Background(), &bundleDeployments)).To(Succeed())
87+
88+
Expect(namesFromList(&operators)).To(BeEmpty(), "operators left in the cluster")
89+
Expect(namesFromList(&bundleDeployments)).To(BeEmpty(), "bundle deployments left in the cluster")
90+
8091
By("tearing down the test environment")
8192
err := testEnv.Stop()
8293
Expect(err).NotTo(HaveOccurred())
8394
})
95+
96+
func namesFromList(list client.ObjectList) []string {
97+
var names []string
98+
99+
items, err := meta.ExtractList(list)
100+
Expect(err).NotTo(HaveOccurred())
101+
for _, item := range items {
102+
names = append(names, item.(client.Object).GetName())
103+
}
104+
return names
105+
}

0 commit comments

Comments
 (0)