Skip to content

Commit 21b2777

Browse files
committed
add unit test for testing all components failing individually during subsequent reconcile
Signed-off-by: everettraven <[email protected]>
1 parent 3963157 commit 21b2777

File tree

2 files changed

+178
-1
lines changed

2 files changed

+178
-1
lines changed

internal/controllers/clusterextension_controller_test.go

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,182 @@ func TestClusterExtensionDeleteFinalizerFails(t *testing.T) {
682682
require.Contains(t, cond.Message, finalizersMessage)
683683
}
684684

685+
func TestClusterExtensionUpgradeFails(t *testing.T) {
686+
cl, reconciler := newClientAndReconciler(t)
687+
reconciler.Unpacker = &MockUnpacker{
688+
result: &source.Result{
689+
State: source.StateUnpacked,
690+
Bundle: fstest.MapFS{},
691+
},
692+
}
693+
694+
ctx := context.Background()
695+
extKey := types.NamespacedName{Name: fmt.Sprintf("cluster-extension-test-%s", rand.String(8))}
696+
697+
t.Log("When the cluster extension specifies a channel with version that exist")
698+
t.Log("By initializing cluster state")
699+
pkgName := "prometheus"
700+
pkgVer := "1.0.0"
701+
pkgChan := "beta"
702+
namespace := fmt.Sprintf("test-ns-%s", rand.String(8))
703+
serviceAccount := fmt.Sprintf("test-sa-%s", rand.String(8))
704+
705+
clusterExtension := &ocv1alpha1.ClusterExtension{
706+
ObjectMeta: metav1.ObjectMeta{Name: extKey.Name},
707+
Spec: ocv1alpha1.ClusterExtensionSpec{
708+
Source: ocv1alpha1.SourceConfig{
709+
SourceType: "Catalog",
710+
Catalog: &ocv1alpha1.CatalogSource{
711+
PackageName: pkgName,
712+
Version: pkgVer,
713+
Channels: []string{pkgChan},
714+
},
715+
},
716+
Install: ocv1alpha1.ClusterExtensionInstallConfig{
717+
Namespace: namespace,
718+
ServiceAccount: ocv1alpha1.ServiceAccountReference{
719+
Name: serviceAccount,
720+
},
721+
},
722+
},
723+
}
724+
err := cl.Create(ctx, clusterExtension)
725+
require.NoError(t, err)
726+
727+
t.Log("It sets resolution success status")
728+
t.Log("By running reconcile")
729+
reconciler.Resolver = resolve.Func(func(_ context.Context, _ *ocv1alpha1.ClusterExtension, _ *ocv1alpha1.BundleMetadata) (*declcfg.Bundle, *bsemver.Version, *declcfg.Deprecation, error) {
730+
v := bsemver.MustParse("1.0.0")
731+
return &declcfg.Bundle{
732+
Name: "prometheus.v1.0.0",
733+
Package: "prometheus",
734+
Image: "quay.io/operatorhubio/[email protected]",
735+
}, &v, nil, nil
736+
})
737+
reconciler.Applier = &MockApplier{
738+
objs: []client.Object{},
739+
}
740+
reconciler.Manager = &MockManagedContentCacheManager{
741+
cache: &MockManagedContentCache{},
742+
}
743+
res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: extKey})
744+
require.Equal(t, ctrl.Result{}, res)
745+
require.NoError(t, err)
746+
747+
t.Log("By fetching updated cluster extension after reconcile")
748+
require.NoError(t, cl.Get(ctx, extKey, clusterExtension))
749+
750+
t.Log("By checking the status fields")
751+
require.Equal(t, ocv1alpha1.BundleMetadata{Name: "prometheus.v1.0.0", Version: "1.0.0"}, clusterExtension.Status.Install.Bundle)
752+
753+
t.Log("By checking the expected installed conditions")
754+
installedCond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1alpha1.TypeInstalled)
755+
require.NotNil(t, installedCond)
756+
require.Equal(t, metav1.ConditionTrue, installedCond.Status)
757+
require.Equal(t, ocv1alpha1.ReasonSucceeded, installedCond.Reason)
758+
759+
t.Log("By checking the expected progressing conditions")
760+
progressingCond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1alpha1.TypeProgressing)
761+
require.NotNil(t, progressingCond)
762+
require.Equal(t, metav1.ConditionFalse, progressingCond.Status)
763+
require.Equal(t, ocv1alpha1.ReasonSucceeded, progressingCond.Reason)
764+
765+
tcs := []struct {
766+
name string
767+
modification func(*controllers.ClusterExtensionReconciler)
768+
}{
769+
{
770+
name: "getting installed bundle fails",
771+
modification: func(cer *controllers.ClusterExtensionReconciler) {
772+
cer.InstalledBundleGetter = &MockInstalledBundleGetter{
773+
bundle: nil,
774+
err: errors.New("boom"),
775+
}
776+
},
777+
},
778+
{
779+
name: "resolution fails",
780+
modification: func(cer *controllers.ClusterExtensionReconciler) {
781+
cer.Resolver = resolve.Func(func(_ context.Context, _ *ocv1alpha1.ClusterExtension, _ *ocv1alpha1.BundleMetadata) (*declcfg.Bundle, *bsemver.Version, *declcfg.Deprecation, error) {
782+
return nil, nil, nil, errors.New("boom")
783+
})
784+
},
785+
},
786+
{
787+
name: "unpack fails",
788+
modification: func(cer *controllers.ClusterExtensionReconciler) {
789+
cer.Unpacker = &MockUnpacker{
790+
err: errors.New("boom"),
791+
}
792+
},
793+
},
794+
{
795+
name: "applier fails",
796+
modification: func(cer *controllers.ClusterExtensionReconciler) {
797+
cer.Applier = &MockApplier{
798+
err: errors.New("boom"),
799+
}
800+
},
801+
},
802+
}
803+
for _, tc := range tcs {
804+
t.Run(tc.name, func(t *testing.T) {
805+
t.Log("By resetting the reconciler")
806+
reconciler.InstalledBundleGetter = &MockInstalledBundleGetter{
807+
bundle: &ocv1alpha1.BundleMetadata{Name: "prometheus.v1.0.0", Version: "1.0.0"},
808+
}
809+
reconciler.Unpacker = &MockUnpacker{
810+
result: &source.Result{
811+
State: source.StateUnpacked,
812+
Bundle: fstest.MapFS{},
813+
},
814+
}
815+
reconciler.Resolver = resolve.Func(func(_ context.Context, _ *ocv1alpha1.ClusterExtension, _ *ocv1alpha1.BundleMetadata) (*declcfg.Bundle, *bsemver.Version, *declcfg.Deprecation, error) {
816+
v := bsemver.MustParse("1.0.0")
817+
return &declcfg.Bundle{
818+
Name: "prometheus.v1.0.0",
819+
Package: "prometheus",
820+
Image: "quay.io/operatorhubio/[email protected]",
821+
}, &v, nil, nil
822+
})
823+
reconciler.Applier = &MockApplier{
824+
objs: []client.Object{},
825+
}
826+
// Here we modify the reconciler to test that a failure of each
827+
// step up until the installation is successful results in no modification
828+
// of the existing Installed condition and associated fields, but does
829+
// result in modification of the Progressing condition to communicate the
830+
// failure.
831+
t.Log("By modifying the reconciler to fail on next reconcile")
832+
tc.modification(reconciler)
833+
834+
t.Log("By running reconciliation again")
835+
res, err = reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: extKey})
836+
require.Equal(t, ctrl.Result{}, res)
837+
require.Error(t, err)
838+
839+
t.Log("By fetching updated cluster extension after reconcile")
840+
require.NoError(t, cl.Get(ctx, extKey, clusterExtension))
841+
842+
t.Log("By checking the status fields")
843+
require.Equal(t, ocv1alpha1.BundleMetadata{Name: "prometheus.v1.0.0", Version: "1.0.0"}, clusterExtension.Status.Install.Bundle)
844+
845+
t.Log("By checking the expected installed conditions")
846+
installedCond = apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1alpha1.TypeInstalled)
847+
require.NotNil(t, installedCond)
848+
require.Equal(t, metav1.ConditionTrue, installedCond.Status)
849+
require.Equal(t, ocv1alpha1.ReasonSucceeded, installedCond.Reason)
850+
851+
t.Log("By checking the expected progressing conditions")
852+
progressingCond = apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1alpha1.TypeProgressing)
853+
require.NotNil(t, progressingCond)
854+
require.Equal(t, metav1.ConditionTrue, progressingCond.Status)
855+
require.Equal(t, ocv1alpha1.ReasonRetrying, progressingCond.Reason)
856+
})
857+
}
858+
require.NoError(t, cl.DeleteAllOf(ctx, &ocv1alpha1.ClusterExtension{}))
859+
}
860+
685861
func verifyInvariants(ctx context.Context, t *testing.T, c client.Client, ext *ocv1alpha1.ClusterExtension) {
686862
key := client.ObjectKeyFromObject(ext)
687863
require.NoError(t, c.Get(ctx, key, ext))

internal/controllers/suite_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,15 @@ func newClient(t *testing.T) client.Client {
7474

7575
type MockInstalledBundleGetter struct {
7676
bundle *ocv1alpha1.BundleMetadata
77+
err error
7778
}
7879

7980
func (m *MockInstalledBundleGetter) SetBundle(bundle *ocv1alpha1.BundleMetadata) {
8081
m.bundle = bundle
8182
}
8283

8384
func (m *MockInstalledBundleGetter) GetInstalledBundle(ctx context.Context, ext *ocv1alpha1.ClusterExtension) (*ocv1alpha1.BundleMetadata, error) {
84-
return m.bundle, nil
85+
return m.bundle, m.err
8586
}
8687

8788
var _ controllers.Applier = (*MockApplier)(nil)

0 commit comments

Comments
 (0)