Skip to content

Commit 177fad2

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

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
@@ -53,6 +53,11 @@ var _ = Describe("Operator Controller Test", func() {
5353
BeforeEach(func() {
5454
opKey = types.NamespacedName{Name: fmt.Sprintf("operator-test-%s", rand.String(8))}
5555
})
56+
AfterEach(func() {
57+
verifyInvariants(ctx, reconciler.Client, operator)
58+
Expect(cl.DeleteAllOf(ctx, &operatorsv1alpha1.Operator{})).To(Succeed())
59+
Expect(cl.DeleteAllOf(ctx, &rukpakv1alpha1.BundleDeployment{})).To(Succeed())
60+
})
5661
When("the operator specifies a non-existent package", func() {
5762
var pkgName string
5863
BeforeEach(func() {
@@ -138,7 +143,6 @@ var _ = Describe("Operator Controller Test", func() {
138143
err := cl.Create(ctx, operator)
139144
Expect(err).NotTo(HaveOccurred())
140145
})
141-
142146
When("the BundleDeployment does not exist", func() {
143147
BeforeEach(func() {
144148
By("running reconcile")
@@ -211,16 +215,16 @@ var _ = Describe("Operator Controller Test", func() {
211215
},
212216
},
213217
}
214-
215218
})
216219

217220
When("the BundleDeployment spec is out of date", func() {
218-
It("results in the expected BundleDeployment", func() {
221+
BeforeEach(func() {
219222
By("modifying the BD spec and creating the object")
220223
bd.Spec.ProvisionerClassName = "core-rukpak-io-helm"
221224
err := cl.Create(ctx, bd)
222225
Expect(err).NotTo(HaveOccurred())
223-
226+
})
227+
It("results in the expected BundleDeployment", func() {
224228
By("running reconcile")
225229
res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey})
226230
Expect(res).To(Equal(ctrl.Result{}))
@@ -509,17 +513,12 @@ var _ = Describe("Operator Controller Test", func() {
509513
})
510514

511515
})
512-
513-
AfterEach(func() {
514-
err := cl.Delete(ctx, bd)
515-
Expect(err).NotTo(HaveOccurred())
516-
})
517-
518516
})
519517
When("an out-of-date BundleDeployment exists", func() {
518+
var bd *rukpakv1alpha1.BundleDeployment
520519
BeforeEach(func() {
521520
By("creating the expected BD")
522-
err := cl.Create(ctx, &rukpakv1alpha1.BundleDeployment{
521+
bd = &rukpakv1alpha1.BundleDeployment{
523522
ObjectMeta: metav1.ObjectMeta{Name: opKey.Name},
524523
Spec: rukpakv1alpha1.BundleDeploymentSpec{
525524
ProvisionerClassName: "foo",
@@ -535,7 +534,8 @@ var _ = Describe("Operator Controller Test", func() {
535534
},
536535
},
537536
},
538-
})
537+
}
538+
err := cl.Create(ctx, bd)
539539
Expect(err).NotTo(HaveOccurred())
540540

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

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

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

1024-
func verifyInvariants(ctx context.Context, op *operatorsv1alpha1.Operator) {
962+
func verifyInvariants(ctx context.Context, c client.Client, op *operatorsv1alpha1.Operator) {
1025963
key := client.ObjectKeyFromObject(op)
1026-
err := cl.Get(ctx, key, op)
964+
err := c.Get(ctx, key, op)
1027965
Expect(err).To(BeNil())
1028966

1029967
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)