@@ -16,6 +16,7 @@ import (
16
16
"k8s.io/utils/pointer"
17
17
ctrl "sigs.k8s.io/controller-runtime"
18
18
"sigs.k8s.io/controller-runtime/pkg/client"
19
+ "sigs.k8s.io/controller-runtime/pkg/client/fake"
19
20
20
21
operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
21
22
"github.com/operator-framework/operator-controller/controllers"
@@ -80,6 +81,38 @@ var _ = Describe("Operator Controller Test", func() {
80
81
Expect (cond .Message ).To (Equal (fmt .Sprintf ("package '%s' not found" , pkgName )))
81
82
})
82
83
})
84
+ When ("the operator specifies a version that does not exist" , func () {
85
+ var pkgName string
86
+ BeforeEach (func () {
87
+ By ("initializing cluster state" )
88
+ pkgName = fmt .Sprintf ("exists-%s" , rand .String (6 ))
89
+ operator = & operatorsv1alpha1.Operator {
90
+ ObjectMeta : metav1.ObjectMeta {Name : opKey .Name },
91
+ Spec : operatorsv1alpha1.OperatorSpec {
92
+ PackageName : pkgName ,
93
+ Version : "0.50.0" , // this version of the package does not exist
94
+ },
95
+ }
96
+ err := cl .Create (ctx , operator )
97
+ Expect (err ).NotTo (HaveOccurred ())
98
+ })
99
+ It ("sets resolution failure status" , func () {
100
+ By ("running reconcile" )
101
+ res , err := reconciler .Reconcile (ctx , ctrl.Request {NamespacedName : opKey })
102
+ Expect (res ).To (Equal (ctrl.Result {}))
103
+ Expect (err ).To (MatchError (fmt .Sprintf ("package '%s' at version '0.50.0' not found" , pkgName )))
104
+
105
+ By ("fetching updated operator after reconcile" )
106
+ Expect (cl .Get (ctx , opKey , operator )).NotTo (HaveOccurred ())
107
+
108
+ By ("checking the expected conditions" )
109
+ cond := apimeta .FindStatusCondition (operator .Status .Conditions , operatorsv1alpha1 .TypeReady )
110
+ Expect (cond ).NotTo (BeNil ())
111
+ Expect (cond .Status ).To (Equal (metav1 .ConditionFalse ))
112
+ Expect (cond .Reason ).To (Equal (operatorsv1alpha1 .ReasonResolutionFailed ))
113
+ Expect (cond .Message ).To (Equal (fmt .Sprintf ("package '%s' at version '0.50.0' not found" , pkgName )))
114
+ })
115
+ })
83
116
When ("the operator specifies a valid available package" , func () {
84
117
const pkgName = "prometheus"
85
118
BeforeEach (func () {
@@ -568,6 +601,54 @@ var _ = Describe("Operator Controller Test", func() {
568
601
Expect (err ).To (Not (HaveOccurred ()))
569
602
})
570
603
})
604
+ When ("an invalid semver is provided that bypasses the regex validation" , func () {
605
+ var (
606
+ operator * operatorsv1alpha1.Operator
607
+ opKey types.NamespacedName
608
+ pkgName string
609
+ fakeClient client.Client
610
+ )
611
+ BeforeEach (func () {
612
+ opKey = types.NamespacedName {Name : fmt .Sprintf ("operator-validation-test-%s" , rand .String (8 ))}
613
+
614
+ By ("injecting creating a client with the bad operator CR" )
615
+ pkgName = fmt .Sprintf ("exists-%s" , rand .String (6 ))
616
+ operator = & operatorsv1alpha1.Operator {
617
+ ObjectMeta : metav1.ObjectMeta {Name : opKey .Name },
618
+ Spec : operatorsv1alpha1.OperatorSpec {
619
+ PackageName : pkgName ,
620
+ Version : "1.2.3-123abc_def" , // bad semver that matches the regex on the CR validation
621
+ },
622
+ }
623
+
624
+ // this bypasses client/server-side CR validation and allows us to test the reconciler's validation
625
+ fakeClient = fake .NewClientBuilder ().WithScheme (sch ).WithObjects (operator ).Build ()
626
+
627
+ By ("changing the reconciler client to the fake client" )
628
+ reconciler .Client = fakeClient
629
+ })
630
+ AfterEach (func () {
631
+ By ("changing the reconciler client back to the real client" )
632
+ reconciler .Client = cl
633
+ })
634
+
635
+ It ("should add an invalid spec condition and *not* re-enqueue for reconciliation" , func () {
636
+ By ("running reconcile" )
637
+ res , err := reconciler .Reconcile (ctx , ctrl.Request {NamespacedName : opKey })
638
+ Expect (res ).To (Equal (ctrl.Result {}))
639
+ Expect (err ).ToNot (HaveOccurred ())
640
+
641
+ By ("fetching updated operator after reconcile" )
642
+ Expect (fakeClient .Get (ctx , opKey , operator )).NotTo (HaveOccurred ())
643
+
644
+ By ("checking the expected conditions" )
645
+ cond := apimeta .FindStatusCondition (operator .Status .Conditions , operatorsv1alpha1 .TypeReady )
646
+ Expect (cond ).NotTo (BeNil ())
647
+ Expect (cond .Status ).To (Equal (metav1 .ConditionFalse ))
648
+ Expect (cond .Reason ).To (Equal (operatorsv1alpha1 .ReasonInvalidSpec ))
649
+ Expect (cond .Message ).To (Equal ("invalid .spec.version: Invalid character(s) found in prerelease \" 123abc_def\" " ))
650
+ })
651
+ })
571
652
})
572
653
573
654
func verifyInvariants (ctx context.Context , op * operatorsv1alpha1.Operator ) {
0 commit comments