qontract-reconcile 0.10.1rc1202__py3-none-any.whl → 0.10.2.dev1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. qontract_reconcile-0.10.2.dev1.dist-info/METADATA +500 -0
  2. {qontract_reconcile-0.10.1rc1202.dist-info → qontract_reconcile-0.10.2.dev1.dist-info}/RECORD +12 -130
  3. {qontract_reconcile-0.10.1rc1202.dist-info → qontract_reconcile-0.10.2.dev1.dist-info}/WHEEL +1 -2
  4. {qontract_reconcile-0.10.1rc1202.dist-info → qontract_reconcile-0.10.2.dev1.dist-info}/entry_points.txt +1 -0
  5. reconcile/aws_account_manager/README.md +5 -0
  6. reconcile/change_owners/README.md +34 -0
  7. reconcile/glitchtip/README.md +150 -0
  8. reconcile/gql_definitions/introspection.json +51176 -0
  9. reconcile/run_integration.py +293 -0
  10. reconcile/utils/binary.py +2 -2
  11. reconcile/utils/mr/README.md +198 -0
  12. reconcile/utils/oc_map.py +2 -2
  13. tools/qontract_cli.py +0 -0
  14. qontract_reconcile-0.10.1rc1202.dist-info/METADATA +0 -64
  15. qontract_reconcile-0.10.1rc1202.dist-info/top_level.txt +0 -3
  16. reconcile/test/__init__.py +0 -0
  17. reconcile/test/conftest.py +0 -157
  18. reconcile/test/fixtures.py +0 -24
  19. reconcile/test/saas_auto_promotions_manager/__init__.py +0 -0
  20. reconcile/test/saas_auto_promotions_manager/conftest.py +0 -170
  21. reconcile/test/saas_auto_promotions_manager/merge_request_manager/__init__.py +0 -0
  22. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/__init__.py +0 -0
  23. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py +0 -115
  24. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/data_keys.py +0 -19
  25. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_desired_state.py +0 -66
  26. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py +0 -86
  27. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_mr_parser.py +0 -352
  28. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_reconciler.py +0 -494
  29. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/__init__.py +0 -0
  30. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +0 -25
  31. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_multiple_namespaces.py +0 -37
  32. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_namespace.py +0 -81
  33. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_target.py +0 -61
  34. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_json_path_selector.py +0 -74
  35. reconcile/test/saas_auto_promotions_manager/test_integration_test.py +0 -52
  36. reconcile/test/saas_auto_promotions_manager/utils/__init__.py +0 -0
  37. reconcile/test/test_acs_notifiers.py +0 -393
  38. reconcile/test/test_acs_policies.py +0 -497
  39. reconcile/test/test_acs_rbac.py +0 -865
  40. reconcile/test/test_aggregated_list.py +0 -237
  41. reconcile/test/test_amtool.py +0 -37
  42. reconcile/test/test_aws_ami_cleanup.py +0 -230
  43. reconcile/test/test_aws_ami_share.py +0 -68
  44. reconcile/test/test_aws_cloudwatch_log_retention.py +0 -434
  45. reconcile/test/test_aws_iam_keys.py +0 -70
  46. reconcile/test/test_aws_iam_password_reset.py +0 -35
  47. reconcile/test/test_aws_support_cases_sos.py +0 -23
  48. reconcile/test/test_checkpoint.py +0 -178
  49. reconcile/test/test_cli.py +0 -41
  50. reconcile/test/test_closedbox_endpoint_monitoring.py +0 -207
  51. reconcile/test/test_dashdotdb_dora.py +0 -245
  52. reconcile/test/test_database_access_manager.py +0 -660
  53. reconcile/test/test_deadmanssnitch.py +0 -290
  54. reconcile/test/test_gabi_authorized_users.py +0 -72
  55. reconcile/test/test_gcr_mirror.py +0 -14
  56. reconcile/test/test_github_org.py +0 -156
  57. reconcile/test/test_github_repo_invites.py +0 -119
  58. reconcile/test/test_gitlab_housekeeping.py +0 -333
  59. reconcile/test/test_gitlab_labeler.py +0 -126
  60. reconcile/test/test_gitlab_members.py +0 -219
  61. reconcile/test/test_gitlab_permissions.py +0 -164
  62. reconcile/test/test_instrumented_wrappers.py +0 -18
  63. reconcile/test/test_integrations_manager.py +0 -1252
  64. reconcile/test/test_jenkins_worker_fleets.py +0 -57
  65. reconcile/test/test_jira_permissions_validator.py +0 -519
  66. reconcile/test/test_jump_host.py +0 -114
  67. reconcile/test/test_ldap_users.py +0 -125
  68. reconcile/test/test_make.py +0 -28
  69. reconcile/test/test_ocm_additional_routers.py +0 -133
  70. reconcile/test/test_ocm_clusters.py +0 -798
  71. reconcile/test/test_ocm_clusters_manifest_updates.py +0 -87
  72. reconcile/test/test_ocm_machine_pools.py +0 -1103
  73. reconcile/test/test_ocm_update_recommended_version.py +0 -145
  74. reconcile/test/test_ocm_upgrade_scheduler_org_updater.py +0 -125
  75. reconcile/test/test_openshift_base.py +0 -1269
  76. reconcile/test/test_openshift_cluster_bots.py +0 -240
  77. reconcile/test/test_openshift_namespace_labels.py +0 -344
  78. reconcile/test/test_openshift_namespaces.py +0 -256
  79. reconcile/test/test_openshift_resource.py +0 -443
  80. reconcile/test/test_openshift_resources_base.py +0 -478
  81. reconcile/test/test_openshift_saas_deploy.py +0 -188
  82. reconcile/test/test_openshift_saas_deploy_change_tester.py +0 -308
  83. reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py +0 -65
  84. reconcile/test/test_openshift_serviceaccount_tokens.py +0 -282
  85. reconcile/test/test_openshift_tekton_resources.py +0 -265
  86. reconcile/test/test_openshift_upgrade_watcher.py +0 -223
  87. reconcile/test/test_prometheus_rules_tester.py +0 -151
  88. reconcile/test/test_quay_membership.py +0 -86
  89. reconcile/test/test_quay_mirror.py +0 -172
  90. reconcile/test/test_quay_mirror_org.py +0 -82
  91. reconcile/test/test_quay_repos.py +0 -59
  92. reconcile/test/test_queries.py +0 -53
  93. reconcile/test/test_repo_owners.py +0 -47
  94. reconcile/test/test_requests_sender.py +0 -139
  95. reconcile/test/test_saasherder.py +0 -1611
  96. reconcile/test/test_saasherder_allowed_secret_paths.py +0 -125
  97. reconcile/test/test_secret_reader.py +0 -153
  98. reconcile/test/test_slack_base.py +0 -183
  99. reconcile/test/test_slack_usergroups.py +0 -785
  100. reconcile/test/test_sql_query.py +0 -316
  101. reconcile/test/test_status_board.py +0 -258
  102. reconcile/test/test_terraform_aws_route53.py +0 -29
  103. reconcile/test/test_terraform_cloudflare_dns.py +0 -117
  104. reconcile/test/test_terraform_cloudflare_resources.py +0 -408
  105. reconcile/test/test_terraform_cloudflare_users.py +0 -747
  106. reconcile/test/test_terraform_repo.py +0 -440
  107. reconcile/test/test_terraform_resources.py +0 -519
  108. reconcile/test/test_terraform_tgw_attachments.py +0 -1295
  109. reconcile/test/test_terraform_users.py +0 -152
  110. reconcile/test/test_terraform_vpc_peerings.py +0 -576
  111. reconcile/test/test_terraform_vpc_peerings_build_desired_state.py +0 -1434
  112. reconcile/test/test_three_way_diff_strategy.py +0 -131
  113. reconcile/test/test_utils_jinja2.py +0 -130
  114. reconcile/test/test_vault_replication.py +0 -534
  115. reconcile/test/test_vault_utils.py +0 -47
  116. reconcile/test/test_version_bump.py +0 -18
  117. reconcile/test/test_vpc_peerings_validator.py +0 -194
  118. reconcile/test/test_wrong_region.py +0 -78
  119. release/__init__.py +0 -0
  120. release/test_version.py +0 -50
  121. release/version.py +0 -104
  122. tools/cli_commands/test/__init__.py +0 -0
  123. tools/cli_commands/test/conftest.py +0 -332
  124. tools/cli_commands/test/test_aws_cost_report.py +0 -258
  125. tools/cli_commands/test/test_cost_management_api.py +0 -326
  126. tools/cli_commands/test/test_gpg_encrypt.py +0 -235
  127. tools/cli_commands/test/test_openshift_cost_optimization_report.py +0 -255
  128. tools/cli_commands/test/test_openshift_cost_report.py +0 -295
  129. tools/cli_commands/test/test_util.py +0 -70
  130. tools/test/__init__.py +0 -0
  131. tools/test/conftest.py +0 -77
  132. tools/test/test_app_interface_metrics_exporter.py +0 -48
  133. tools/test/test_erv2.py +0 -80
  134. tools/test/test_get_container_images.py +0 -230
  135. tools/test/test_qontract_cli.py +0 -197
  136. tools/test/test_saas_promotion_state.py +0 -187
  137. tools/test/test_sd_app_sre_alert_report.py +0 -74
  138. tools/test/test_sre_checkpoints.py +0 -79
@@ -1,1269 +0,0 @@
1
- import logging
2
- from collections.abc import Mapping
3
- from typing import Any
4
- from unittest.mock import patch
5
-
6
- import pytest
7
- import yaml
8
- from kubernetes.dynamic import Resource
9
- from pydantic import BaseModel
10
- from pytest_mock import MockerFixture
11
-
12
- import reconcile.openshift_base as sut
13
- import reconcile.utils.openshift_resource as resource
14
- from reconcile.test.fixtures import Fixtures
15
- from reconcile.utils import oc
16
- from reconcile.utils.differ import (
17
- DiffPair,
18
- DiffResult,
19
- )
20
- from reconcile.utils.semver_helper import make_semver
21
-
22
- fxt = Fixtures("namespaces")
23
-
24
-
25
- TEST_INT = "test_openshift_resources"
26
- TEST_INT_VER = make_semver(1, 9, 2)
27
-
28
-
29
- def build_resource(kind: str, api_version: str, name: str) -> dict[str, Any]:
30
- return {
31
- "kind": kind,
32
- "apiVersion": api_version,
33
- "metadata": {
34
- "name": name,
35
- },
36
- }
37
-
38
-
39
- @pytest.fixture
40
- def resource_inventory() -> resource.ResourceInventory:
41
- return resource.ResourceInventory()
42
-
43
-
44
- @pytest.fixture
45
- def namespaces() -> list[dict[str, Any]]:
46
- return [fxt.get_anymarkup("valid-ns.yml")]
47
-
48
-
49
- @pytest.fixture
50
- @patch("reconcile.utils.oc.OCNative")
51
- def oc_cs1(self) -> oc.OCClient:
52
- return oc.OCNative(cluster_name="cs1", server="server", token="token", local=True)
53
-
54
-
55
- @pytest.fixture
56
- def oc_map(mocker, oc_cs1: oc.OCNative) -> oc.OC_Map:
57
- def get_cluster(cluster: str, privileged: bool = False):
58
- if cluster == "cs1":
59
- return oc_cs1
60
-
61
- return (
62
- oc.OCLogMsg(
63
- log_level=logging.DEBUG, message=f"[{cluster}] cluster skipped"
64
- ),
65
- )
66
-
67
- oc_map = mocker.patch("reconcile.utils.oc.OC_Map", autospec=True).return_value
68
- oc_map.get.side_effect = get_cluster
69
- return oc_map
70
-
71
-
72
- #
73
- # init_specs_to_fetch tests
74
- #
75
-
76
-
77
- def test_only_cluster_or_namespace(
78
- resource_inventory: resource.ResourceInventory, oc_map: oc.OC_Map
79
- ) -> None:
80
- with pytest.raises(KeyError):
81
- sut.init_specs_to_fetch(
82
- ri=resource_inventory,
83
- oc_map=oc_map,
84
- namespaces=[{"foo": "bar"}],
85
- clusters=[{"name": "cs1"}],
86
- )
87
-
88
-
89
- def test_no_cluster_or_namespace(
90
- resource_inventory: resource.ResourceInventory, oc_map: oc.OC_Map
91
- ) -> None:
92
- with pytest.raises(KeyError):
93
- sut.init_specs_to_fetch(
94
- ri=resource_inventory, oc_map=oc_map, namespaces=None, clusters=None
95
- )
96
-
97
-
98
- def test_namespaces_managed_types(
99
- resource_inventory: resource.ResourceInventory,
100
- oc_map: oc.OC_Map,
101
- oc_cs1: oc.OCNative,
102
- ) -> None:
103
- namespace = yaml.safe_load(
104
- """
105
- name: ns1
106
- cluster:
107
- name: cs1
108
- managedResourceTypes:
109
- - Template
110
- managedResourceNames:
111
- - resource: Template
112
- resourceNames:
113
- - tp1
114
- - tp2
115
- openshiftResources:
116
- - provider: resource
117
- path: /some/path.yml
118
- """
119
- )
120
- expected: list[sut.StateSpec] = [
121
- sut.CurrentStateSpec(
122
- oc=oc_cs1,
123
- cluster="cs1",
124
- namespace="ns1",
125
- kind="Template",
126
- resource_names=["tp1", "tp2"],
127
- ),
128
- sut.DesiredStateSpec(
129
- oc=oc_cs1,
130
- cluster="cs1",
131
- namespace="ns1",
132
- resource={"provider": "resource", "path": "/some/path.yml"},
133
- parent=namespace,
134
- ),
135
- ]
136
-
137
- rs = sut.init_specs_to_fetch(
138
- resource_inventory,
139
- oc_map,
140
- namespaces=[namespace],
141
- )
142
- assert rs == expected
143
-
144
-
145
- def test_namespaces_managed_types_with_resoruce_type_overrides(
146
- resource_inventory: resource.ResourceInventory,
147
- oc_map: oc.OC_Map,
148
- oc_cs1: oc.OCNative,
149
- ) -> None:
150
- namespace = yaml.safe_load(
151
- """
152
- name: ns1
153
- cluster:
154
- name: cs1
155
- managedResourceTypes:
156
- - Template
157
- managedResourceNames:
158
- - resource: Template
159
- resourceNames:
160
- - tp1
161
- - tp2
162
- managedResourceTypeOverrides:
163
- - resource: Template
164
- "override": "Template.something.something"
165
- openshiftResources:
166
- - provider: resource
167
- path: /some/path.yml
168
- """
169
- )
170
- expected: list[sut.StateSpec] = [
171
- sut.CurrentStateSpec(
172
- oc=oc_cs1,
173
- cluster="cs1",
174
- namespace="ns1",
175
- kind="Template.something.something",
176
- resource_names=["tp1", "tp2"],
177
- ),
178
- sut.DesiredStateSpec(
179
- oc=oc_cs1,
180
- cluster="cs1",
181
- namespace="ns1",
182
- resource={"provider": "resource", "path": "/some/path.yml"},
183
- parent=namespace,
184
- ),
185
- ]
186
- rs = sut.init_specs_to_fetch(
187
- resource_inventory,
188
- oc_map,
189
- namespaces=[namespace],
190
- )
191
-
192
- assert rs == expected
193
-
194
-
195
- def test_namespaces_managed_types_no_managed_resource_names(
196
- resource_inventory: resource.ResourceInventory,
197
- oc_map: oc.OC_Map,
198
- oc_cs1: oc.OCNative,
199
- ) -> None:
200
- namespace = yaml.safe_load(
201
- """
202
- name: ns1
203
- cluster:
204
- name: cs1
205
- managedResourceTypes:
206
- - Template
207
- openshiftResources:
208
- - provider: resource
209
- path: /some/path.yml
210
- """
211
- )
212
- expected: list[sut.StateSpec] = [
213
- sut.CurrentStateSpec(
214
- oc=oc_cs1,
215
- cluster="cs1",
216
- namespace="ns1",
217
- kind="Template",
218
- resource_names=None,
219
- ),
220
- sut.DesiredStateSpec(
221
- oc=oc_cs1,
222
- cluster="cs1",
223
- namespace="ns1",
224
- resource={"provider": "resource", "path": "/some/path.yml"},
225
- parent=namespace,
226
- ),
227
- ]
228
- rs = sut.init_specs_to_fetch(
229
- resource_inventory,
230
- oc_map,
231
- namespaces=[namespace],
232
- )
233
- assert rs == expected
234
-
235
-
236
- def test_namespaces_no_managed_resource_types(
237
- resource_inventory: resource.ResourceInventory,
238
- oc_map: oc.OC_Map,
239
- ) -> None:
240
- namespace = yaml.safe_load(
241
- """
242
- name: ns1
243
- cluster:
244
- name: cs1
245
- openshiftResources:
246
- - provider: resource
247
- path: /some/path.yml
248
- """
249
- )
250
- rs = sut.init_specs_to_fetch(
251
- resource_inventory,
252
- oc_map,
253
- namespaces=[namespace],
254
- )
255
-
256
- assert not rs
257
-
258
-
259
- def test_namespaces_resources_names_for_unmanaged_type(
260
- resource_inventory: resource.ResourceInventory,
261
- oc_map: oc.OC_Map,
262
- ) -> None:
263
- namespace = yaml.safe_load(
264
- """
265
- name: ns1
266
- cluster:
267
- name: cs1
268
- managedResourceTypes:
269
- - Template
270
- managedResourceNames:
271
- - resource: Template
272
- resourceNames:
273
- - tp1
274
- - tp2
275
- - resource: Secret
276
- resourceNames:
277
- - s1
278
- - s2
279
- openshiftResources:
280
- - provider: resource
281
- path: /some/path.yml
282
- """
283
- )
284
-
285
- with pytest.raises(KeyError):
286
- sut.init_specs_to_fetch(
287
- resource_inventory,
288
- oc_map,
289
- namespaces=[namespace],
290
- )
291
-
292
-
293
- def test_namespaces_type_override_for_unmanaged_type(
294
- resource_inventory: resource.ResourceInventory,
295
- oc_map: oc.OC_Map,
296
- ) -> None:
297
- namespace = yaml.safe_load(
298
- """
299
- name: ns1
300
- cluster:
301
- name: cs1
302
- managedResourceTypes:
303
- - Template
304
- managedResourceTypeOverrides:
305
- - resource: UnmanagedType
306
- override: UnmanagedType.unmanagedapi
307
- openshiftResources:
308
- - provider: resource
309
- path: /some/path.yml
310
- """
311
- )
312
- with pytest.raises(KeyError):
313
- sut.init_specs_to_fetch(resource_inventory, oc_map, namespaces=[namespace])
314
-
315
-
316
- def test_namespaces_override_managed_type(
317
- resource_inventory: resource.ResourceInventory,
318
- oc_map: oc.OC_Map,
319
- oc_cs1: oc.OCNative,
320
- ) -> None:
321
- """
322
- test that the override_managed_types parameter for init_specs_to_fetch takes
323
- precedence over what might be defined on the namespace. this is relevant for
324
- integrations that specifically handle only a subset of types e.g. terraform-resources
325
- only managing Secrets
326
- """
327
- namespace = yaml.safe_load(
328
- """
329
- name: ns1
330
- cluster:
331
- name: cs1
332
- managedResourceTypes:
333
- - Template
334
- managedResourceNames:
335
- - resource: Template
336
- resourceNames:
337
- - tp1
338
- - tp2
339
- openshiftResources:
340
- - provider: resource
341
- path: /some/path.yml
342
- """
343
- )
344
- expected: list[sut.StateSpec] = [
345
- sut.CurrentStateSpec(
346
- oc=oc_cs1,
347
- cluster="cs1",
348
- namespace="ns1",
349
- kind="LimitRanges",
350
- resource_names=None,
351
- ),
352
- sut.DesiredStateSpec(
353
- oc=oc_cs1,
354
- cluster="cs1",
355
- namespace="ns1",
356
- resource={"provider": "resource", "path": "/some/path.yml"},
357
- parent=namespace,
358
- ),
359
- ]
360
-
361
- rs = sut.init_specs_to_fetch(
362
- resource_inventory,
363
- oc_map=oc_map,
364
- namespaces=[namespace],
365
- override_managed_types=["LimitRanges"],
366
- )
367
- assert rs == expected
368
-
369
- registrations = list(resource_inventory)
370
- # make sure only the override_managed_type LimitRange is present
371
- # and not the Template from the namespace
372
- assert len(registrations) == 1
373
- cluster, ns, kind, _ = registrations[0]
374
- assert (cluster, ns, kind) == ("cs1", "ns1", "LimitRanges")
375
-
376
-
377
- def test_namespaces_managed_fully_qualified_types(
378
- resource_inventory: resource.ResourceInventory,
379
- oc_map: oc.OC_Map,
380
- oc_cs1: oc.OCNative,
381
- ) -> None:
382
- namespace = yaml.safe_load(
383
- """
384
- name: ns1
385
- cluster:
386
- name: cs1
387
- managedResourceTypes:
388
- - Kind.fully.qualified
389
- openshiftResources:
390
- - provider: resource
391
- path: /some/path.yml
392
- """
393
- )
394
- expected: list[sut.StateSpec] = [
395
- sut.CurrentStateSpec(
396
- oc=oc_cs1,
397
- cluster="cs1",
398
- namespace="ns1",
399
- kind="Kind.fully.qualified",
400
- resource_names=None,
401
- ),
402
- sut.DesiredStateSpec(
403
- oc=oc_cs1,
404
- cluster="cs1",
405
- namespace="ns1",
406
- resource={"provider": "resource", "path": "/some/path.yml"},
407
- parent=namespace,
408
- ),
409
- ]
410
-
411
- rs = sut.init_specs_to_fetch(
412
- resource_inventory,
413
- oc_map,
414
- namespaces=[namespace],
415
- )
416
- assert rs == expected
417
-
418
-
419
- def test_namespaces_managed_fully_qualified_types_with_resource_names(
420
- resource_inventory: resource.ResourceInventory,
421
- oc_map: oc.OC_Map,
422
- oc_cs1: oc.OCNative,
423
- ) -> None:
424
- namespace = yaml.safe_load(
425
- """
426
- name: ns1
427
- cluster:
428
- name: cs1
429
- managedResourceTypes:
430
- - Kind.fully.qualified
431
- managedResourceNames:
432
- - resource: Kind.fully.qualified
433
- resourceNames:
434
- - n1
435
- - n2
436
- openshiftResources:
437
- - provider: resource
438
- path: /some/path.yml
439
- """
440
- )
441
- expected: list[sut.StateSpec] = [
442
- sut.CurrentStateSpec(
443
- oc=oc_cs1,
444
- cluster="cs1",
445
- namespace="ns1",
446
- kind="Kind.fully.qualified",
447
- resource_names=["n1", "n2"],
448
- ),
449
- sut.DesiredStateSpec(
450
- oc=oc_cs1,
451
- cluster="cs1",
452
- namespace="ns1",
453
- resource={"provider": "resource", "path": "/some/path.yml"},
454
- parent=namespace,
455
- ),
456
- ]
457
-
458
- rs = sut.init_specs_to_fetch(
459
- resource_inventory,
460
- oc_map,
461
- namespaces=[namespace],
462
- )
463
- assert rs == expected
464
-
465
-
466
- def test_namespaces_managed_mixed_qualified_types_with_resource_names(
467
- resource_inventory: resource.ResourceInventory,
468
- oc_map: oc.OC_Map,
469
- oc_cs1: oc.OCNative,
470
- ) -> None:
471
- namespace = yaml.safe_load(
472
- """
473
- name: ns1
474
- cluster:
475
- name: cs1
476
- managedResourceTypes:
477
- - Kind.fully.qualified
478
- - Kind
479
- managedResourceNames:
480
- - resource: Kind.fully.qualified
481
- resourceNames:
482
- - fname
483
- - resource: Kind
484
- resourceNames:
485
- - name
486
- openshiftResources:
487
- - provider: resource
488
- path: /some/path.yml
489
- """
490
- )
491
- expected: list[sut.StateSpec] = [
492
- sut.CurrentStateSpec(
493
- oc=oc_cs1,
494
- cluster="cs1",
495
- namespace="ns1",
496
- kind="Kind.fully.qualified",
497
- resource_names=["fname"],
498
- ),
499
- sut.CurrentStateSpec(
500
- oc=oc_cs1,
501
- cluster="cs1",
502
- namespace="ns1",
503
- kind="Kind",
504
- resource_names=["name"],
505
- ),
506
- sut.DesiredStateSpec(
507
- oc=oc_cs1,
508
- cluster="cs1",
509
- namespace="ns1",
510
- resource={"provider": "resource", "path": "/some/path.yml"},
511
- parent=namespace,
512
- ),
513
- ]
514
-
515
- rs = sut.init_specs_to_fetch(
516
- resource_inventory,
517
- oc_map,
518
- namespaces=[namespace],
519
- )
520
-
521
- assert len(expected) == len(rs)
522
- for e in expected:
523
- assert e in rs
524
-
525
-
526
- #
527
- # populate state tests
528
- #
529
-
530
-
531
- @pytest.fixture
532
- def api_resources():
533
- r1 = Resource(
534
- prefix="",
535
- kind="Kind",
536
- group="fully.qualified",
537
- api_version="v1",
538
- namespaced=True,
539
- )
540
- r2 = Resource(
541
- prefix="",
542
- kind="Kind",
543
- group="another.group",
544
- api_version="v1",
545
- namespaced=True,
546
- )
547
- return {"Kind": [r1, r2]}
548
-
549
-
550
- def test_populate_current_state(
551
- api_resources, resource_inventory: resource.ResourceInventory, oc_cs1: oc.OCNative
552
- ):
553
- """
554
- test that populate_current_state properly populates the resource inventory
555
- """
556
- # prepare client and resource inventory
557
- oc_cs1.init_api_resources = True
558
- oc_cs1.api_resources = api_resources
559
- oc_cs1.get_items = lambda kind, **kwargs: [
560
- build_resource("Kind", "fully.qualified/v1", "name")
561
- ]
562
- resource_inventory.initialize_resource_type("cs1", "ns1", "Kind.fully.qualified")
563
-
564
- # process
565
- spec = sut.CurrentStateSpec(
566
- oc=oc_cs1,
567
- cluster="cs1",
568
- namespace="ns1",
569
- kind="Kind.fully.qualified",
570
- resource_names=["name"],
571
- )
572
- sut.populate_current_state(spec, resource_inventory, TEST_INT, TEST_INT_VER)
573
-
574
- # verify
575
- cluster, namespace, kind, data = next(iter(resource_inventory))
576
- assert (cluster, namespace, kind) == ("cs1", "ns1", "Kind.fully.qualified")
577
- assert data["current"]["name"] == resource.OpenshiftResource(
578
- build_resource("Kind", "fully.qualified/v1", "name"), TEST_INT, TEST_INT_VER
579
- )
580
-
581
-
582
- def test_populate_current_state_unknown_kind(
583
- resource_inventory: resource.ResourceInventory, oc_cs1: oc.OCNative, mocker
584
- ):
585
- """
586
- test that a missing kind in the cluster is catched early on
587
- """
588
- oc_cs1.init_api_resources = True
589
- k1 = Resource(prefix="", group="some.other.group", api_version="v1", kind="Kind")
590
- oc_cs1.api_resources = {"Kind": [k1]}
591
- get_item_mock = mocker.patch.object(oc.OCNative, "get_items", autospec=True)
592
-
593
- spec = sut.CurrentStateSpec(
594
- oc=oc_cs1,
595
- cluster="cs1",
596
- namespace="ns1",
597
- kind="Kind.fully.qualified",
598
- resource_names=["name"],
599
- )
600
- sut.populate_current_state(spec, resource_inventory, TEST_INT, TEST_INT_VER)
601
-
602
- assert len(list(iter(resource_inventory))) == 0
603
- get_item_mock.assert_not_called()
604
-
605
-
606
- def test_populate_current_state_resource_name_filtering(
607
- resource_inventory: resource.ResourceInventory, oc_cs1: oc.OCNative, mocker
608
- ):
609
- """
610
- test if the resource names are passed properly to the oc client when fetching items
611
- """
612
- spec = sut.CurrentStateSpec(
613
- oc=oc_cs1,
614
- cluster="cs1",
615
- namespace="ns1",
616
- kind="Kind.fully.qualified",
617
- resource_names=["name1", "name2"],
618
- )
619
- sut.populate_current_state(spec, resource_inventory, TEST_INT, TEST_INT_VER)
620
-
621
- oc_cs1.get_items.assert_called_with(
622
- "Kind.fully.qualified",
623
- namespace="ns1",
624
- resource_names=["name1", "name2"],
625
- )
626
-
627
-
628
- #
629
- # determine_user_keys_for_access tests
630
- #
631
-
632
-
633
- class OpenshiftBaseAuthService(BaseModel):
634
- service: str
635
-
636
-
637
- class OpenshiftBaseCluster(BaseModel):
638
- name: str
639
- auth: list[OpenshiftBaseAuthService]
640
-
641
-
642
- class OpenshiftBaseUser(BaseModel):
643
- org_username: str
644
- github_username: str
645
-
646
-
647
- @pytest.mark.parametrize(
648
- "auth, expected",
649
- [
650
- # dicts
651
- ([{"service": "github-org"}], ["github_username"]),
652
- ([{"service": "github-org-team"}], ["github_username"]),
653
- ([{"service": "oidc"}], ["org_username"]),
654
- (
655
- [{"service": "oidc"}, {"service": "github-org-team"}],
656
- ["org_username", "github_username"],
657
- ),
658
- (
659
- [{"service": "github-org"}, {"service": "github-org-team"}],
660
- ["github_username"],
661
- ),
662
- # class
663
- ([OpenshiftBaseAuthService(service="github-org")], ["github_username"]),
664
- ([OpenshiftBaseAuthService(service="github-org-team")], ["github_username"]),
665
- ([OpenshiftBaseAuthService(service="oidc")], ["org_username"]),
666
- (
667
- [
668
- OpenshiftBaseAuthService(service="oidc"),
669
- OpenshiftBaseAuthService(service="github-org-team"),
670
- ],
671
- ["org_username", "github_username"],
672
- ),
673
- (
674
- [
675
- OpenshiftBaseAuthService(service="github-org"),
676
- OpenshiftBaseAuthService(service="github-org-team"),
677
- ],
678
- ["github_username"],
679
- ),
680
- # backward_compatibility
681
- ([], ["github_username"]),
682
- ],
683
- )
684
- def test_determine_user_keys_for_access(auth, expected):
685
- assert sut.determine_user_keys_for_access("cluster-name", auth) == expected
686
-
687
-
688
- def test_determine_user_keys_enforced_user_keys():
689
- assert sut.determine_user_keys_for_access(
690
- "cluster-name",
691
- [{"service": "github-org"}],
692
- enforced_user_keys=["my-enforced-key"],
693
- ) == ["my-enforced-key"]
694
-
695
-
696
- def test_determine_user_keys_for_access_not_implemented():
697
- auth = {"service": "not-implemented"}
698
- with pytest.raises(NotImplementedError):
699
- sut.determine_user_keys_for_access("cluster-name", [auth])
700
-
701
-
702
- def test_is_namespace_deleted_true():
703
- ns = {"delete": True}
704
- assert sut.is_namespace_deleted(ns) is True
705
-
706
-
707
- def test_is_namespace_deleted_false():
708
- ns = {"delete": False}
709
- assert sut.is_namespace_deleted(ns) is False
710
-
711
-
712
- def test_is_namespace_deleted_none():
713
- ns = {"delete": None}
714
- assert sut.is_namespace_deleted(ns) is False
715
-
716
-
717
- def test_is_namespace_deleted_empty():
718
- assert sut.is_namespace_deleted({}) is False
719
-
720
-
721
- def test_user_has_cluster_access(mocker: MockerFixture):
722
- mocker.patch.object(
723
- sut, "determine_user_keys_for_access", return_value=["org_username"]
724
- )
725
- user = OpenshiftBaseUser(org_username="user_org", github_username="user_github")
726
- cluster = OpenshiftBaseCluster(
727
- name="cluster", auth=[OpenshiftBaseAuthService(service="oidc")]
728
- )
729
- assert sut.user_has_cluster_access(user, cluster, ["user_org"])
730
- assert not sut.user_has_cluster_access(user, cluster, ["another_user"])
731
-
732
-
733
- @pytest.fixture
734
- def apply_options() -> sut.ApplyOptions:
735
- options = sut.ApplyOptions(
736
- dry_run=True,
737
- no_dry_run_skip_compare=False,
738
- wait_for_namespace=True,
739
- recycle_pods=True,
740
- take_over=False,
741
- override_enable_deletion=False,
742
- caller="saas-test",
743
- all_callers=["saas-test"],
744
- privileged=False,
745
- enable_deletion=False,
746
- )
747
- return options
748
-
749
-
750
- def build_openshift_resource(
751
- kind: str,
752
- api_version: str,
753
- name: str,
754
- extra_body: dict[str, Any] | None,
755
- integration: str = "",
756
- integration_version: str = "",
757
- error_details: str = "",
758
- caller_name: str = "",
759
- ) -> resource.OpenshiftResource:
760
- body = {
761
- "kind": kind,
762
- "apiVersion": api_version,
763
- "metadata": {"name": name},
764
- }
765
- if extra_body:
766
- body |= extra_body
767
-
768
- return resource.OpenshiftResource(
769
- body=body,
770
- integration=integration,
771
- integration_version=integration_version,
772
- error_details=error_details,
773
- caller_name=caller_name,
774
- validate_k8s_object=False,
775
- )
776
-
777
-
778
- def build_openshift_resource_1() -> resource.OpenshiftResource:
779
- spec = {"spec": {"test-attr": "test-value-1"}}
780
- return build_openshift_resource(
781
- kind="test-kind",
782
- api_version="v1",
783
- name="test-resource",
784
- extra_body=spec,
785
- caller_name="saas-test",
786
- )
787
-
788
-
789
- def build_openshift_resource_2() -> resource.OpenshiftResource:
790
- spec = {"spec": {"test-attr": "test-value-2"}}
791
- return build_openshift_resource(
792
- kind="test-kind",
793
- api_version="v1",
794
- name="test-resource",
795
- extra_body=spec,
796
- caller_name="saas-test",
797
- )
798
-
799
-
800
- @pytest.fixture
801
- def diff_result() -> DiffResult:
802
- r1 = build_openshift_resource_1()
803
- r2 = build_openshift_resource_2()
804
- return DiffResult(
805
- add={"test-resource": r1},
806
- change={"test-resource": DiffPair(r1, r2)},
807
- delete={"test-resource": r1},
808
- identical={"test-resource": DiffPair(r1, r1)},
809
- )
810
-
811
-
812
- def test_handle_new_resources(
813
- mocker: MockerFixture,
814
- oc_map: oc.OC_Map,
815
- resource_inventory: resource.ResourceInventory,
816
- diff_result: DiffResult,
817
- apply_options: sut.ApplyOptions,
818
- ):
819
- apply_mock = mocker.patch.object(sut, "apply", autospec=True)
820
- cluster = "test-cluster"
821
- namespace = "test-namespace"
822
- resource_type = "test-Kind"
823
- data = {"use_admin_token": {"test-resource": False}}
824
-
825
- actions = sut.handle_new_resources(
826
- oc_map=oc_map,
827
- ri=resource_inventory,
828
- new_resources=diff_result.add,
829
- cluster=cluster,
830
- namespace=namespace,
831
- resource_type=resource_type,
832
- data=data,
833
- options=apply_options,
834
- )
835
-
836
- assert len(actions) == 1
837
- apply_expected_args = {
838
- "dry_run": True,
839
- "oc_map": oc_map,
840
- "cluster": "test-cluster",
841
- "namespace": "test-namespace",
842
- "resource_type": "test-Kind",
843
- "resource": diff_result.add["test-resource"],
844
- "wait_for_namespace": True,
845
- "recycle_pods": True,
846
- "privileged": False,
847
- }
848
- apply_mock.assert_called_with(**apply_expected_args)
849
-
850
-
851
- @pytest.mark.parametrize(
852
- "apply_options, should_apply, should_error_ri",
853
- [
854
- ( # Same Caller. The resource should be updated
855
- sut.ApplyOptions(
856
- dry_run=True,
857
- no_dry_run_skip_compare=False,
858
- wait_for_namespace=True,
859
- recycle_pods=True,
860
- take_over=False,
861
- override_enable_deletion=False,
862
- caller="saas-test",
863
- all_callers=["saas-test"],
864
- privileged=False,
865
- enable_deletion=False,
866
- ),
867
- True,
868
- False,
869
- ),
870
- ( # The resource is owned by "saas-test" but is present in "different".
871
- # An error must be raised
872
- sut.ApplyOptions(
873
- dry_run=True,
874
- no_dry_run_skip_compare=False,
875
- wait_for_namespace=True,
876
- recycle_pods=True,
877
- take_over=False,
878
- override_enable_deletion=False,
879
- caller="different",
880
- all_callers=["saas-test", "different"],
881
- privileged=False,
882
- enable_deletion=False,
883
- ),
884
- False,
885
- True,
886
- ),
887
- ( # The Resource is owned by "saas-test" and is being deployed by "different"
888
- # Since "saas-test" is not in all_callers it means it has been
889
- # deprecated. The Resource needs to be taken over by "different"
890
- sut.ApplyOptions(
891
- dry_run=True,
892
- no_dry_run_skip_compare=False,
893
- wait_for_namespace=True,
894
- recycle_pods=True,
895
- take_over=False,
896
- override_enable_deletion=False,
897
- caller="different",
898
- all_callers=["different"],
899
- privileged=False,
900
- enable_deletion=False,
901
- ),
902
- True,
903
- False,
904
- ),
905
- ( # Take over resources from another Saas-file
906
- sut.ApplyOptions(
907
- dry_run=True,
908
- no_dry_run_skip_compare=False,
909
- wait_for_namespace=True,
910
- recycle_pods=True,
911
- take_over=True,
912
- override_enable_deletion=False,
913
- caller="different",
914
- all_callers=["saas-test", "different"],
915
- privileged=False,
916
- enable_deletion=False,
917
- ),
918
- True,
919
- False,
920
- ),
921
- ],
922
- )
923
- def test_handle_modified_resources(
924
- mocker: MockerFixture,
925
- oc_map: oc.OC_Map,
926
- resource_inventory: resource.ResourceInventory,
927
- diff_result: DiffResult,
928
- apply_options: sut.ApplyOptions,
929
- should_apply: bool,
930
- should_error_ri: bool,
931
- ):
932
- apply_mock = mocker.patch.object(sut, "apply", autospec=True)
933
- cluster = "test-cluster"
934
- namespace = "test-namespace"
935
- resource_type = "test-Kind"
936
- data = {"use_admin_token": {"test-resource": False}}
937
-
938
- modified_resources = diff_result.change
939
-
940
- actions = sut.handle_modified_resources(
941
- oc_map=oc_map,
942
- ri=resource_inventory,
943
- modified_resources=modified_resources,
944
- cluster=cluster,
945
- namespace=namespace,
946
- resource_type=resource_type,
947
- data=data,
948
- options=apply_options,
949
- )
950
-
951
- if should_apply:
952
- assert len(actions) == 1
953
- apply_expected_args = {
954
- "dry_run": True,
955
- "oc_map": oc_map,
956
- "cluster": "test-cluster",
957
- "namespace": "test-namespace",
958
- "resource_type": "test-Kind",
959
- "resource": diff_result.change["test-resource"].desired,
960
- "wait_for_namespace": True,
961
- "recycle_pods": True,
962
- "privileged": False,
963
- }
964
- apply_mock.assert_called_with(**apply_expected_args)
965
- else:
966
- assert len(actions) == 0
967
-
968
- if should_error_ri:
969
- assert resource_inventory._error_registered
970
-
971
-
972
- @pytest.mark.parametrize(
973
- "apply_options, should_take_over, should_error_ri",
974
- [
975
- ( # Same Caller and Identical Resource. Nothing should happen
976
- sut.ApplyOptions(
977
- dry_run=True,
978
- no_dry_run_skip_compare=False,
979
- wait_for_namespace=True,
980
- recycle_pods=True,
981
- take_over=False,
982
- override_enable_deletion=False,
983
- caller="saas-test",
984
- all_callers=["saas-test"],
985
- privileged=False,
986
- enable_deletion=False,
987
- ),
988
- False,
989
- False,
990
- ),
991
- ( # The resource is owned by "saas-test" but is present in "different".
992
- # An error must be raised
993
- sut.ApplyOptions(
994
- dry_run=True,
995
- no_dry_run_skip_compare=False,
996
- wait_for_namespace=True,
997
- recycle_pods=True,
998
- take_over=False,
999
- override_enable_deletion=False,
1000
- caller="different",
1001
- all_callers=["saas-test", "different"],
1002
- privileged=False,
1003
- enable_deletion=False,
1004
- ),
1005
- False,
1006
- True,
1007
- ),
1008
- ( # The Resource is owned by "saas-test" and is being deployed by "different"
1009
- # Since "saas-test" is not in all_callers it means it has been
1010
- # deprecated. The Resource needs to be taken over by "different"
1011
- sut.ApplyOptions(
1012
- dry_run=True,
1013
- no_dry_run_skip_compare=False,
1014
- wait_for_namespace=True,
1015
- recycle_pods=True,
1016
- take_over=False,
1017
- override_enable_deletion=False,
1018
- caller="different",
1019
- all_callers=["different"],
1020
- privileged=False,
1021
- enable_deletion=False,
1022
- ),
1023
- True,
1024
- False,
1025
- ),
1026
- ( # Take over resources from another Saas-file
1027
- sut.ApplyOptions(
1028
- dry_run=True,
1029
- no_dry_run_skip_compare=False,
1030
- wait_for_namespace=True,
1031
- recycle_pods=True,
1032
- take_over=True,
1033
- override_enable_deletion=False,
1034
- caller="different",
1035
- all_callers=["saas-test", "different"],
1036
- privileged=False,
1037
- enable_deletion=False,
1038
- ),
1039
- True,
1040
- False,
1041
- ),
1042
- ],
1043
- )
1044
- def test_handle_identical_resources(
1045
- mocker: MockerFixture,
1046
- oc_map: oc.OC_Map,
1047
- resource_inventory: resource.ResourceInventory,
1048
- diff_result: DiffResult,
1049
- apply_options: sut.ApplyOptions,
1050
- should_take_over: bool,
1051
- should_error_ri: bool,
1052
- ):
1053
- apply_mock = mocker.patch.object(sut, "apply", autospec=True)
1054
- cluster = "test-cluster"
1055
- namespace = "test-namespace"
1056
- resource_type = "test-Kind"
1057
- data = {"use_admin_token": {"test-resource": False}}
1058
-
1059
- actions = sut.handle_identical_resources(
1060
- oc_map=oc_map,
1061
- ri=resource_inventory,
1062
- identical_resources=diff_result.identical,
1063
- cluster=cluster,
1064
- namespace=namespace,
1065
- resource_type=resource_type,
1066
- data=data,
1067
- options=apply_options,
1068
- )
1069
-
1070
- if should_take_over:
1071
- assert len(actions) == 1
1072
- apply_expected_args = {
1073
- "dry_run": True,
1074
- "oc_map": oc_map,
1075
- "cluster": "test-cluster",
1076
- "namespace": "test-namespace",
1077
- "resource_type": "test-Kind",
1078
- "resource": diff_result.identical["test-resource"].desired,
1079
- "wait_for_namespace": True,
1080
- "recycle_pods": True,
1081
- "privileged": False,
1082
- }
1083
- apply_mock.assert_called_with(**apply_expected_args)
1084
- else:
1085
- assert len(actions) == 0
1086
- if should_error_ri:
1087
- assert resource_inventory._error_registered
1088
-
1089
-
1090
- def test_handle_deleted_resources(
1091
- mocker: MockerFixture,
1092
- oc_map: oc.OC_Map,
1093
- resource_inventory: resource.ResourceInventory,
1094
- diff_result: DiffResult,
1095
- apply_options: sut.ApplyOptions,
1096
- ):
1097
- delete_mock = mocker.patch.object(sut, "delete", autospec=True)
1098
-
1099
- # mock has_qontract_annotations to own the resource
1100
- hqa = mocker.patch.object(
1101
- resource.OpenshiftResource, "has_qontract_annotations", autospec=True
1102
- )
1103
- hqa.return_value = True
1104
-
1105
- cluster = "test-cluster"
1106
- namespace = "test-namespace"
1107
- resource_type = "test-Kind"
1108
- data = {"use_admin_token": {"test-resource": False}}
1109
-
1110
- actions = sut.handle_deleted_resources(
1111
- oc_map=oc_map,
1112
- ri=resource_inventory,
1113
- deleted_resources=diff_result.delete,
1114
- cluster=cluster,
1115
- namespace=namespace,
1116
- resource_type=resource_type,
1117
- data=data,
1118
- options=apply_options,
1119
- )
1120
-
1121
- assert len(actions) == 1
1122
- delete_expected_args = {
1123
- "dry_run": True,
1124
- "oc_map": oc_map,
1125
- "cluster": "test-cluster",
1126
- "namespace": "test-namespace",
1127
- "resource_type": "test-Kind",
1128
- "name": "test-resource",
1129
- "enable_deletion": False,
1130
- "privileged": False,
1131
- }
1132
- delete_mock.assert_called_with(**delete_expected_args)
1133
-
1134
-
1135
- # Fixtures does not work with parametrize
1136
- # functions are used to build resources instead
1137
- @pytest.mark.parametrize(
1138
- "data, len_actions, apply_calls, delete_calls",
1139
- [
1140
- (
1141
- {
1142
- "current": {},
1143
- "desired": {"test-resource": build_openshift_resource_1()},
1144
- "use_admin_token": {},
1145
- },
1146
- 1,
1147
- 1,
1148
- 0,
1149
- ),
1150
- (
1151
- {
1152
- "current": {"test-resource": build_openshift_resource_1()},
1153
- "desired": {"test-resource": build_openshift_resource_2()},
1154
- "use_admin_token": {},
1155
- },
1156
- 1,
1157
- 1,
1158
- 0,
1159
- ),
1160
- (
1161
- {
1162
- "current": {"test-resource": build_openshift_resource_1()},
1163
- "desired": {},
1164
- "use_admin_token": {},
1165
- },
1166
- 1,
1167
- 0,
1168
- 1,
1169
- ),
1170
- ],
1171
- )
1172
- def test_realize_resource_data_3way_diff(
1173
- mocker: MockerFixture,
1174
- oc_map: oc.OC_Map,
1175
- resource_inventory: resource.ResourceInventory,
1176
- apply_options: sut.ApplyOptions,
1177
- data: Mapping[str, Any],
1178
- len_actions: int,
1179
- apply_calls: int,
1180
- delete_calls: int,
1181
- ):
1182
- apply_mock = mocker.patch.object(sut, "apply", autospec=True)
1183
- delete_mock = mocker.patch.object(sut, "delete", autospec=True)
1184
- # Patch has_qontract_annotations to own the resource
1185
- mocker.patch.object(
1186
- resource.OpenshiftResource, "has_qontract_annotations", autospec=True
1187
- ).return_value = True
1188
-
1189
- ri_item = ("test-cluster", "test-namespace", "test-kind", data)
1190
- actions = sut._realize_resource_data_3way_diff(
1191
- ri_item=ri_item, oc_map=oc_map, ri=resource_inventory, options=apply_options
1192
- )
1193
- assert len(actions) == len_actions
1194
- assert apply_mock.call_count == apply_calls
1195
- assert delete_mock.call_count == delete_calls
1196
-
1197
-
1198
- def test_get_state_count_combinations():
1199
- state = [
1200
- {"cluster": "c1"},
1201
- {"cluster": "c2"},
1202
- {"cluster": "c1"},
1203
- {"cluster": "c3"},
1204
- {"cluster": "c2"},
1205
- ]
1206
- expected = {"c1": 2, "c2": 2, "c3": 1}
1207
- assert expected == sut.get_state_count_combinations(state)
1208
-
1209
-
1210
- def test_aggregate_shared_resources_typed_openshift_service_resources() -> None:
1211
- class OpenShiftResourcesStub(BaseModel):
1212
- openshift_resources: list | None
1213
-
1214
- class OpenShiftResourcesAndSharedResourcesStub(OpenShiftResourcesStub, BaseModel):
1215
- shared_resources: list[OpenShiftResourcesStub] | None
1216
-
1217
- namespace = OpenShiftResourcesAndSharedResourcesStub(
1218
- openshift_resources=[1], shared_resources=None
1219
- )
1220
- sut.aggregate_shared_resources_typed(namespace=namespace)
1221
- assert namespace.openshift_resources == [1]
1222
-
1223
- namespace = OpenShiftResourcesAndSharedResourcesStub(
1224
- openshift_resources=None,
1225
- shared_resources=[OpenShiftResourcesStub(openshift_resources=[2])],
1226
- )
1227
- sut.aggregate_shared_resources_typed(namespace=namespace)
1228
- assert namespace.openshift_resources == [2]
1229
-
1230
- namespace = OpenShiftResourcesAndSharedResourcesStub(
1231
- openshift_resources=[1],
1232
- shared_resources=[OpenShiftResourcesStub(openshift_resources=[2])],
1233
- )
1234
- sut.aggregate_shared_resources_typed(namespace=namespace)
1235
- assert namespace.openshift_resources == [1, 2]
1236
-
1237
-
1238
- def test_aggregate_shared_resources_typed_openshift_service_account_token() -> None:
1239
- class OpenshiftServiceAccountTokensStub(BaseModel):
1240
- openshift_service_account_tokens: list | None
1241
-
1242
- class OpenshiftServiceAccountTokensAndSharedResourcesStub(
1243
- OpenshiftServiceAccountTokensStub, BaseModel
1244
- ):
1245
- shared_resources: list[OpenshiftServiceAccountTokensStub] | None
1246
-
1247
- namespace = OpenshiftServiceAccountTokensAndSharedResourcesStub(
1248
- openshift_service_account_tokens=[1], shared_resources=None
1249
- )
1250
- sut.aggregate_shared_resources_typed(namespace=namespace)
1251
- assert namespace.openshift_service_account_tokens == [1]
1252
-
1253
- namespace = OpenshiftServiceAccountTokensAndSharedResourcesStub(
1254
- openshift_service_account_tokens=None,
1255
- shared_resources=[
1256
- OpenshiftServiceAccountTokensStub(openshift_service_account_tokens=[2])
1257
- ],
1258
- )
1259
- sut.aggregate_shared_resources_typed(namespace=namespace)
1260
- assert namespace.openshift_service_account_tokens == [2]
1261
-
1262
- namespace = OpenshiftServiceAccountTokensAndSharedResourcesStub(
1263
- openshift_service_account_tokens=[1],
1264
- shared_resources=[
1265
- OpenshiftServiceAccountTokensStub(openshift_service_account_tokens=[2])
1266
- ],
1267
- )
1268
- sut.aggregate_shared_resources_typed(namespace=namespace)
1269
- assert namespace.openshift_service_account_tokens == [1, 2]