2323
2424class MockResource :
2525 """Mock Kubernetes resource object"""
26+
2627 def __init__ (self , name , labels = None , owner_refs = None , csv_names = None , phase = "Complete" ):
2728 self .metadata = Mock ()
2829 self .metadata .name = name
2930 self .metadata .labels = labels or {}
3031 self .metadata .ownerReferences = owner_refs or []
31-
32+
3233 self .spec = Mock ()
3334 self .spec .clusterServiceVersionNames = csv_names or []
34-
35+
3536 self .status = Mock ()
3637 self .status .phase = phase
3738
3839
3940class MockResourceList :
4041 """Mock Kubernetes resource list"""
42+
4143 def __init__ (self , items ):
4244 self .items = items
4345
@@ -93,12 +95,12 @@ def test_automatic_approval_uses_label_selector_only(
9395 mock_get_manifest .return_value = Mock (
9496 status = Mock (defaultChannel = "stable" , catalogSource = "test-catalog" )
9597 )
96-
98+
9799 # Mock subscription API
98100 sub_api = Mock ()
99101 sub_api .get .return_value = MockResourceList ([]) # No existing subscription
100102 sub_api .apply .return_value = Mock ()
101-
103+
102104 # Mock InstallPlan API - label selector returns one InstallPlan
103105 install_plan_api = Mock ()
104106 install_plan = MockResource (
@@ -108,13 +110,13 @@ def test_automatic_approval_uses_label_selector_only(
108110 phase = "Complete"
109111 )
110112 install_plan_api .get .return_value = MockResourceList ([install_plan ])
111-
113+
112114 # Setup resource API
113115 mock_dyn_client .resources .get .side_effect = lambda ** kwargs : {
114116 ("operators.coreos.com/v1alpha1" , "Subscription" ): sub_api ,
115117 ("operators.coreos.com/v1alpha1" , "InstallPlan" ): install_plan_api ,
116118 }.get ((kwargs .get ("api_version" ), kwargs .get ("kind" )))
117-
119+
118120 with patch ('mas.devops.olm.Environment' , return_value = mock_env ):
119121 # Call applySubscription with Automatic approval (default)
120122 olm .applySubscription (
@@ -124,10 +126,10 @@ def test_automatic_approval_uses_label_selector_only(
124126 packageChannel = "stable" ,
125127 installPlanApproval = "Automatic"
126128 )
127-
129+
128130 # Verify InstallPlan API was called with label selector only
129131 install_plan_calls = [c for c in install_plan_api .get .call_args_list ]
130-
132+
131133 # Should only use label selector, never query all InstallPlans
132134 for call_args in install_plan_calls :
133135 args , kwargs = call_args
@@ -150,12 +152,12 @@ def test_manual_approval_without_starting_csv_uses_label_selector_only(
150152 mock_get_manifest .return_value = Mock (
151153 status = Mock (defaultChannel = "stable" , catalogSource = "test-catalog" )
152154 )
153-
155+
154156 # Mock subscription API
155157 sub_api = Mock ()
156158 sub_api .get .return_value = MockResourceList ([])
157159 sub_api .apply .return_value = Mock ()
158-
160+
159161 # Mock InstallPlan API
160162 install_plan_api = Mock ()
161163 install_plan = MockResource (
@@ -166,12 +168,12 @@ def test_manual_approval_without_starting_csv_uses_label_selector_only(
166168 )
167169 install_plan_api .get .return_value = MockResourceList ([install_plan ])
168170 install_plan_api .patch .return_value = Mock ()
169-
171+
170172 mock_dyn_client .resources .get .side_effect = lambda ** kwargs : {
171173 ("operators.coreos.com/v1alpha1" , "Subscription" ): sub_api ,
172174 ("operators.coreos.com/v1alpha1" , "InstallPlan" ): install_plan_api ,
173175 }.get ((kwargs .get ("api_version" ), kwargs .get ("kind" )))
174-
176+
175177 with patch ('mas.devops.olm.Environment' , return_value = mock_env ):
176178 # Call with Manual approval but NO startingCSV
177179 olm .applySubscription (
@@ -181,7 +183,7 @@ def test_manual_approval_without_starting_csv_uses_label_selector_only(
181183 packageChannel = "stable" ,
182184 installPlanApproval = "Manual"
183185 )
184-
186+
185187 # Verify only label selector was used
186188 install_plan_calls = [c for c in install_plan_api .get .call_args_list ]
187189 for call_args in install_plan_calls :
@@ -205,12 +207,12 @@ def test_manual_approval_with_starting_csv_label_selector_finds_match(
205207 mock_get_manifest .return_value = Mock (
206208 status = Mock (defaultChannel = "stable" , catalogSource = "test-catalog" )
207209 )
208-
210+
209211 # Mock subscription API
210212 sub_api = Mock ()
211213 sub_api .get .return_value = MockResourceList ([])
212214 sub_api .apply .return_value = Mock ()
213-
215+
214216 # Mock InstallPlan API - label selector returns matching InstallPlan
215217 install_plan_api = Mock ()
216218 install_plan = MockResource (
@@ -220,12 +222,12 @@ def test_manual_approval_with_starting_csv_label_selector_finds_match(
220222 phase = "Complete"
221223 )
222224 install_plan_api .get .return_value = MockResourceList ([install_plan ])
223-
225+
224226 mock_dyn_client .resources .get .side_effect = lambda ** kwargs : {
225227 ("operators.coreos.com/v1alpha1" , "Subscription" ): sub_api ,
226228 ("operators.coreos.com/v1alpha1" , "InstallPlan" ): install_plan_api ,
227229 }.get ((kwargs .get ("api_version" ), kwargs .get ("kind" )))
228-
230+
229231 with patch ('mas.devops.olm.Environment' , return_value = mock_env ):
230232 olm .applySubscription (
231233 mock_dyn_client ,
@@ -235,11 +237,11 @@ def test_manual_approval_with_starting_csv_label_selector_finds_match(
235237 installPlanApproval = "Manual" ,
236238 startingCSV = "test-operator.v1.0.0"
237239 )
238-
240+
239241 # Verify we found the InstallPlan via label selector
240242 # Should NOT have queried all InstallPlans (no call without label_selector)
241243 install_plan_calls = [c for c in install_plan_api .get .call_args_list ]
242-
244+
243245 # Check that we never queried without a label_selector or name
244246 for call_args in install_plan_calls :
245247 args , kwargs = call_args
@@ -263,23 +265,23 @@ def test_manual_approval_with_starting_csv_fallback_to_ownership_search(
263265 mock_get_manifest .return_value = Mock (
264266 status = Mock (defaultChannel = "stable" , catalogSource = "test-catalog" )
265267 )
266-
268+
267269 # Mock subscription API
268270 sub_api = Mock ()
269271 sub_api .get .return_value = MockResourceList ([])
270272 sub_api .apply .return_value = Mock ()
271-
273+
272274 # Mock InstallPlan API
273275 install_plan_api = Mock ()
274-
276+
275277 # Label selector returns only the in-progress InstallPlan (wrong one)
276278 wrong_install_plan = MockResource (
277279 name = "install-plan-2" ,
278280 labels = {"operators.coreos.com/test-operator.test-namespace" : "" },
279281 csv_names = ["test-operator.v2.0.0" ], # Does NOT match startingCSV
280282 phase = "Installing"
281283 )
282-
284+
283285 # All InstallPlans query returns both (including the completed one)
284286 correct_install_plan = MockResource (
285287 name = "install-plan-1" ,
@@ -288,7 +290,7 @@ def test_manual_approval_with_starting_csv_fallback_to_ownership_search(
288290 csv_names = ["test-operator.v1.0.0" ], # Matches startingCSV
289291 phase = "Complete"
290292 )
291-
293+
292294 # Setup the mock to return different results based on parameters
293295 def get_side_effect (* args , ** kwargs ):
294296 if 'label_selector' in kwargs :
@@ -300,14 +302,14 @@ def get_side_effect(*args, **kwargs):
300302 else :
301303 # Query all InstallPlans - returns both
302304 return MockResourceList ([correct_install_plan , wrong_install_plan ])
303-
305+
304306 install_plan_api .get .side_effect = get_side_effect
305-
307+
306308 mock_dyn_client .resources .get .side_effect = lambda ** kwargs : {
307309 ("operators.coreos.com/v1alpha1" , "Subscription" ): sub_api ,
308310 ("operators.coreos.com/v1alpha1" , "InstallPlan" ): install_plan_api ,
309311 }.get ((kwargs .get ("api_version" ), kwargs .get ("kind" )))
310-
312+
311313 with patch ('mas.devops.olm.Environment' , return_value = mock_env ):
312314 olm .applySubscription (
313315 mock_dyn_client ,
@@ -317,22 +319,22 @@ def get_side_effect(*args, **kwargs):
317319 installPlanApproval = "Manual" ,
318320 startingCSV = "test-operator.v1.0.0"
319321 )
320-
322+
321323 # Verify the fallback behavior occurred
322324 install_plan_calls = [c for c in install_plan_api .get .call_args_list ]
323-
325+
324326 # Should have:
325327 # 1. Called with label_selector (initial query)
326328 # 2. Called without label_selector (fallback to query all)
327329 has_label_selector_call = any (
328- 'label_selector' in call_args [1 ]
330+ 'label_selector' in call_args [1 ]
329331 for call_args in install_plan_calls
330332 )
331333 has_all_query_call = any (
332334 'label_selector' not in call_args [1 ] and 'name' not in call_args [1 ]
333335 for call_args in install_plan_calls
334336 )
335-
337+
336338 assert has_label_selector_call , "Should have tried label selector first"
337339 assert has_all_query_call , "Should have fallen back to querying all InstallPlans"
338340
@@ -352,23 +354,23 @@ def test_manual_approval_filters_by_subscription_ownership(
352354 mock_get_manifest .return_value = Mock (
353355 status = Mock (defaultChannel = "stable" , catalogSource = "test-catalog" )
354356 )
355-
357+
356358 # Mock subscription API
357359 sub_api = Mock ()
358360 sub_api .get .return_value = MockResourceList ([])
359361 sub_api .apply .return_value = Mock ()
360-
362+
361363 # Mock InstallPlan API
362364 install_plan_api = Mock ()
363-
365+
364366 # Label selector returns wrong InstallPlan
365367 wrong_install_plan = MockResource (
366368 name = "install-plan-wrong" ,
367369 labels = {"operators.coreos.com/test-operator.test-namespace" : "" },
368370 csv_names = ["test-operator.v2.0.0" ],
369371 phase = "Installing"
370372 )
371-
373+
372374 # All InstallPlans includes:
373375 # 1. Correct one owned by our subscription
374376 correct_install_plan = MockResource (
@@ -378,7 +380,7 @@ def test_manual_approval_filters_by_subscription_ownership(
378380 csv_names = ["test-operator.v1.0.0" ],
379381 phase = "Complete"
380382 )
381-
383+
382384 # 2. One owned by a different subscription (should be ignored)
383385 other_subscription_plan = MockResource (
384386 name = "install-plan-other" ,
@@ -387,7 +389,7 @@ def test_manual_approval_filters_by_subscription_ownership(
387389 csv_names = ["test-operator.v1.0.0" ], # Same CSV but wrong subscription
388390 phase = "Complete"
389391 )
390-
392+
391393 def get_side_effect (* args , ** kwargs ):
392394 if 'label_selector' in kwargs :
393395 return MockResourceList ([wrong_install_plan ])
@@ -396,14 +398,14 @@ def get_side_effect(*args, **kwargs):
396398 else :
397399 # Return all three InstallPlans
398400 return MockResourceList ([correct_install_plan , other_subscription_plan , wrong_install_plan ])
399-
401+
400402 install_plan_api .get .side_effect = get_side_effect
401-
403+
402404 mock_dyn_client .resources .get .side_effect = lambda ** kwargs : {
403405 ("operators.coreos.com/v1alpha1" , "Subscription" ): sub_api ,
404406 ("operators.coreos.com/v1alpha1" , "InstallPlan" ): install_plan_api ,
405407 }.get ((kwargs .get ("api_version" ), kwargs .get ("kind" )))
406-
408+
407409 with patch ('mas.devops.olm.Environment' , return_value = mock_env ):
408410 olm .applySubscription (
409411 mock_dyn_client ,
@@ -413,7 +415,7 @@ def get_side_effect(*args, **kwargs):
413415 installPlanApproval = "Manual" ,
414416 startingCSV = "test-operator.v1.0.0"
415417 )
416-
418+
417419 # The test passes if it completes without error
418420 # The code should have found the correct InstallPlan by checking ownership
419421 # and ignored the one from the other subscription
0 commit comments