@@ -14,10 +14,230 @@ import (
1414 "k8s.io/apimachinery/pkg/runtime/schema"
1515 "k8s.io/apimachinery/pkg/util/sets"
1616 "k8s.io/apimachinery/pkg/util/yaml"
17+ dynamicfake "k8s.io/client-go/dynamic/fake"
1718
1819 policyv1beta1 "open-cluster-management.io/config-policy-controller/api/v1beta1"
1920)
2021
22+ func TestBuildResources_SubscriptionErrorUpdatesStatus (t * testing.T ) {
23+ t .Parallel ()
24+
25+ r := & OperatorPolicyReconciler {}
26+
27+ policy := & policyv1beta1.OperatorPolicy {
28+ ObjectMeta : metav1.ObjectMeta {
29+ Name : "my-policy" ,
30+ Namespace : "default" ,
31+ Annotations : map [string ]string {
32+ "policy.open-cluster-management.io/disable-templates" : "true" ,
33+ },
34+ },
35+ Spec : policyv1beta1.OperatorPolicySpec {
36+ Severity : "low" ,
37+ RemediationAction : "inform" ,
38+ ComplianceType : "musthave" ,
39+ Subscription : runtime.RawExtension {
40+ Raw : []byte (`{
41+ "namespace": "default",
42+ "source": "my-catalog",
43+ "sourceNamespace": "my-ns",
44+ "name": "",
45+ "channel": "stable"
46+ }` ),
47+ },
48+ UpgradeApproval : "None" ,
49+ },
50+ }
51+
52+ _ , _ , changed , returnedErr := r .buildResources (t .Context (), policy )
53+ assert .True (t , changed , "expected status to be updated" )
54+ assert .NoError (t , returnedErr )
55+
56+ _ , cond := policy .Status .GetCondition (validPolicyConditionType )
57+ assert .Equal (t , metav1 .ConditionFalse , cond .Status )
58+ assert .Equal (t , "InvalidPolicySpec" , cond .Reason )
59+ assert .Equal (t , "name is required in spec.subscription" , cond .Message )
60+ }
61+
62+ func TestBuildResources_subInstallPlanApprovalErrorUpdatesStatus (t * testing.T ) {
63+ t .Parallel ()
64+
65+ r := & OperatorPolicyReconciler {}
66+
67+ policy := & policyv1beta1.OperatorPolicy {
68+ ObjectMeta : metav1.ObjectMeta {
69+ Name : "my-policy" ,
70+ Namespace : "default" ,
71+ Annotations : map [string ]string {
72+ "policy.open-cluster-management.io/disable-templates" : "true" ,
73+ },
74+ },
75+ Spec : policyv1beta1.OperatorPolicySpec {
76+ Severity : "low" ,
77+ RemediationAction : "inform" ,
78+ ComplianceType : "musthave" ,
79+ Subscription : runtime.RawExtension {
80+ Raw : []byte (`{
81+ "namespace": "default",
82+ "source": "my-catalog",
83+ "sourceNamespace": "my-ns",
84+ "name": "my-operator",
85+ "channel": "stable",
86+ "installPlanApproval": "ERR"
87+ }` ),
88+ },
89+ UpgradeApproval : "None" ,
90+ },
91+ }
92+
93+ _ , _ , changed , returnedErr := r .buildResources (t .Context (), policy )
94+ assert .True (t , changed , "expected status to be updated" )
95+ assert .NoError (t , returnedErr )
96+
97+ _ , cond := policy .Status .GetCondition (validPolicyConditionType )
98+ assert .Equal (t , metav1 .ConditionFalse , cond .Status )
99+ assert .Equal (t , "InvalidPolicySpec" , cond .Reason )
100+ assert .Equal (t , "installPlanApproval is prohibited in spec.subscription" , cond .Message )
101+ }
102+
103+ func TestBuildResources_SubDefaultsPkgManifestNotFoundUpdatesStatusAndReturnsErr (t * testing.T ) {
104+ // To test line 542
105+ t .Parallel ()
106+
107+ r := & OperatorPolicyReconciler {
108+ // Use a fake dynamic client without any objects so PackageManifest GET returns NotFound
109+ DynamicClient : dynamicfake .NewSimpleDynamicClient (runtime .NewScheme ()),
110+ }
111+
112+ policy := & policyv1beta1.OperatorPolicy {
113+ ObjectMeta : metav1.ObjectMeta {
114+ Name : "my-policy" ,
115+ Namespace : "default" ,
116+ Annotations : map [string ]string {
117+ "policy.open-cluster-management.io/disable-templates" : "true" ,
118+ },
119+ },
120+ Spec : policyv1beta1.OperatorPolicySpec {
121+ Severity : "low" ,
122+ RemediationAction : "inform" ,
123+ ComplianceType : "musthave" ,
124+ Subscription : runtime.RawExtension {
125+ // Omit namespace key entirely so buildSubscription succeeds with empty namespace,
126+ // and omit source/sourceNamespace so defaultsNeeded = true (triggers PackageManifest lookup).
127+ Raw : []byte (`{
128+ "name": "my-operator",
129+ "channel": "stable",
130+ "startingCSV": "my-operator-v1"
131+ }` ),
132+ },
133+ UpgradeApproval : "None" ,
134+ },
135+ }
136+
137+ sub , opGroup , changed , returnedErr := r .buildResources (t .Context (), policy )
138+ assert .True (t , changed , "expected status to be updated" )
139+ assert .ErrorIs (t , returnedErr , ErrPackageManifest , "expected returned error to wrap ErrPackageManifest" )
140+
141+ _ , cond := policy .Status .GetCondition (validPolicyConditionType )
142+ assert .Equal (t , metav1 .ConditionFalse , cond .Status )
143+ assert .Equal (t , "InvalidPolicySpec" , cond .Reason )
144+ assert .Equal (t ,
145+ "the subscription defaults could not be determined because the PackageManifest was not found" ,
146+ cond .Message )
147+ assert .Nil (t , sub , "expected subscription to be nil" )
148+ assert .Nil (t , opGroup , "expected operator group to be nil" )
149+ }
150+
151+ func TestBuildResources_OperatorGroupErrorUpdatesStatus (t * testing.T ) {
152+ t .Parallel ()
153+
154+ r := & OperatorPolicyReconciler {}
155+
156+ policy := & policyv1beta1.OperatorPolicy {
157+ ObjectMeta : metav1.ObjectMeta {
158+ Name : "my-policy" ,
159+ Namespace : "default" ,
160+ Annotations : map [string ]string {
161+ "policy.open-cluster-management.io/disable-templates" : "true" ,
162+ },
163+ },
164+ Spec : policyv1beta1.OperatorPolicySpec {
165+ Severity : "low" ,
166+ RemediationAction : "inform" ,
167+ ComplianceType : "musthave" ,
168+ Subscription : runtime.RawExtension {
169+ Raw : []byte (`{
170+ "namespace": "default",
171+ "source": "my-catalog",
172+ "sourceNamespace": "my-ns",
173+ "name": "my-operator",
174+ "channel": "stable"
175+ }` ),
176+ },
177+ // Invalid operatorGroup (missing name) should trigger a validation error
178+ OperatorGroup : & runtime.RawExtension {
179+ Raw : []byte (`{}` ),
180+ },
181+ UpgradeApproval : "None" ,
182+ },
183+ }
184+
185+ _ , _ , changed , returnedErr := r .buildResources (t .Context (), policy )
186+ assert .True (t , changed , "expected status to be updated" )
187+ assert .NoError (t , returnedErr )
188+
189+ _ , cond := policy .Status .GetCondition (validPolicyConditionType )
190+ assert .Equal (t , metav1 .ConditionFalse , cond .Status )
191+ assert .Equal (t , "InvalidPolicySpec" , cond .Reason )
192+ assert .Equal (t , "name is required in spec.operatorGroup" , cond .Message )
193+ }
194+
195+ func TestBuildResources_TemplateResolverCreationErrorUpdatesStatus (t * testing.T ) {
196+ t .Parallel ()
197+
198+ r := & OperatorPolicyReconciler {
199+ DynamicWatcher : nil ,
200+ }
201+
202+ policy := & policyv1beta1.OperatorPolicy {
203+ ObjectMeta : metav1.ObjectMeta {
204+ Name : "my-policy" ,
205+ Namespace : "default" ,
206+ },
207+ Spec : policyv1beta1.OperatorPolicySpec {
208+ Severity : "low" ,
209+ RemediationAction : "inform" ,
210+ ComplianceType : "musthave" ,
211+ // Include an obviously bad template so template resolution would fail if reached.
212+ // In this test, resolver creation itself is expected to fail earlier.
213+ Versions : []string {"{{ .badTemplate " },
214+ Subscription : runtime.RawExtension {
215+ Raw : []byte (`{
216+ "namespace": "default",
217+ "name": "my-operator",
218+ "channel": "stable",
219+ "startingCSV": "my-operator-v1"
220+ }` ),
221+ },
222+ UpgradeApproval : "None" ,
223+ },
224+ }
225+
226+ sub , opGroup , changed , returnedErr := r .buildResources (t .Context (), policy )
227+ assert .True (t , changed , "expected status to be updated" )
228+ assert .NoError (t , returnedErr )
229+ assert .Nil (t , sub , "expected subscription to be nil on early return" )
230+ assert .Nil (t , opGroup , "expected operator group to be nil on early return" )
231+
232+ _ , cond := policy .Status .GetCondition (validPolicyConditionType )
233+ assert .Equal (t , metav1 .ConditionFalse , cond .Status )
234+ assert .Equal (t , "InvalidPolicySpec" , cond .Reason )
235+ assert .Equal (t ,
236+ "unable to create template resolver: could not resolve the version template: " +
237+ "failed to parse the template JSON string [\" {{ .badTemplate \" ]: template: tmpl:1: " +
238+ "unterminated character constant" , cond .Message )
239+ }
240+
21241func TestBuildSubscription (t * testing.T ) {
22242 testPolicy := & policyv1beta1.OperatorPolicy {
23243 ObjectMeta : metav1.ObjectMeta {
0 commit comments