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,256 +0,0 @@
1
- import contextlib
2
- import io
3
- from unittest import TestCase
4
- from unittest.mock import (
5
- Mock,
6
- create_autospec,
7
- patch,
8
- )
9
-
10
- from reconcile import openshift_namespaces
11
- from reconcile.gql_definitions.common.app_interface_vault_settings import (
12
- AppInterfaceSettingsV1,
13
- )
14
- from reconcile.gql_definitions.common.namespaces_minimal import NamespaceV1
15
- from reconcile.test.fixtures import Fixtures
16
- from reconcile.utils.oc import StatusCodeError
17
- from reconcile.utils.secret_reader import SecretReaderBase
18
-
19
- fxt = Fixtures("openshift_namespaces")
20
-
21
-
22
- def load_namespace(name: str) -> NamespaceV1:
23
- content = fxt.get_anymarkup(name)
24
- return NamespaceV1(**content)
25
-
26
-
27
- c1, c2 = "cluster1", "cluster2"
28
- n1, n2 = "ns1", "ns2"
29
-
30
-
31
- class NS:
32
- """
33
- Simple utility class holding test information on namesapces
34
- """
35
-
36
- def __init__(self, cluster: str, name: str, delete: bool, exists: bool = True):
37
- self.cluster = cluster
38
- self.name = name
39
- self.delete = delete
40
- self.exists = exists
41
-
42
- def gql(self):
43
- """Get this namespace as an output of GQL"""
44
- ns = load_namespace("namespace.yml")
45
- ns.name = self.name
46
- ns.cluster.name = self.cluster
47
- ns.delete = self.delete
48
- return ns
49
-
50
-
51
- class TestOpenshiftNamespaces(TestCase):
52
- def _oc_map_clusters(self):
53
- """Mock OCM_Map.clusters() by listing clusters in our test data"""
54
- return [ns.name for ns in self.test_ns]
55
-
56
- def _project_exists(self, project) -> bool:
57
- for ns in self.test_ns:
58
- if ns.name == project and ns.cluster == self.current_cluster:
59
- return ns.exists
60
- return False
61
-
62
- def _oc_map_get(self, cluster):
63
- """Mock OCM_Map.get() to return a Mock object"""
64
- self.current_cluster = cluster
65
- if cluster not in self.oc_clients:
66
- # The mock could be set in the test to override this behavior
67
- oc = self.oc_clients.setdefault(cluster, Mock(name=f"oc_{cluster}"))
68
- oc.project_exists.side_effect = self._project_exists
69
- else:
70
- oc = self.oc_clients[cluster]
71
- return oc
72
-
73
- def _queries_get_namespaces(self):
74
- """Mock get_namespaces() by returning our test data
75
- gql_response is set in the test method.
76
- """
77
- return [ns.gql() for ns in self.test_ns]
78
-
79
- def setUp(self):
80
- """Setup GQL, State and Openshift mocks, using self.test_ns data"""
81
- self.oc_clients = {}
82
- self.test_ns = []
83
-
84
- module = "reconcile.openshift_namespaces"
85
-
86
- self.queries_patcher = patch(f"{module}.get_namespaces_minimal", autospec=True)
87
- self.queries = self.queries_patcher.start()
88
- self.queries.side_effect = self._queries_get_namespaces
89
-
90
- vault_settings = AppInterfaceSettingsV1(vault=False)
91
- self.get_vault_settings_patcher = patch(
92
- f"{module}.get_app_interface_vault_settings"
93
- )
94
- self.get_vault_settings = self.get_vault_settings_patcher.start()
95
- self.get_vault_settings.side_effect = [vault_settings]
96
-
97
- self.create_secret_reader_patcher = patch(f"{module}.create_secret_reader")
98
- self.create_secret_reader = self.create_secret_reader_patcher.start()
99
- self.create_secret_reader.side_effect = [create_autospec(spec=SecretReaderBase)]
100
-
101
- self.oc_map_patcher = patch(f"{module}.init_oc_map_from_namespaces")
102
- self.oc_map = self.oc_map_patcher.start().return_value
103
- self.oc_map.clusters.side_effect = self._oc_map_clusters
104
- self.oc_map.get.side_effect = self._oc_map_get
105
-
106
- def tearDown(self) -> None:
107
- self.oc_map_patcher.stop()
108
- self.queries_patcher.stop()
109
-
110
- def test_create_namespace(self):
111
- self.test_ns = [
112
- NS(c1, n1, delete=False, exists=False),
113
- NS(c2, n2, delete=False, exists=False),
114
- ]
115
-
116
- openshift_namespaces.run(False, thread_pool_size=1)
117
-
118
- for ns in self.test_ns:
119
- oc = self.oc_clients[ns.cluster]
120
- oc.new_project.assert_called_with(ns.name)
121
- oc.delete_project.assert_not_called()
122
-
123
- def test_delete_namespace(self):
124
- self.test_ns = [
125
- NS(c1, n1, delete=True, exists=True),
126
- NS(c2, n2, delete=True, exists=True),
127
- ]
128
-
129
- openshift_namespaces.run(False, thread_pool_size=1)
130
-
131
- for ns in self.test_ns:
132
- oc = self.oc_clients[ns.cluster]
133
- oc.delete_project.assert_called_with(ns.name)
134
- oc.new_project.assert_not_called()
135
-
136
- def test_dup_present_namespace_no_deletes_should_do_nothing(self):
137
- self.test_ns = [
138
- NS(c1, n1, delete=False, exists=True),
139
- NS(c1, n1, delete=False, exists=True),
140
- NS(c1, n1, delete=False, exists=True),
141
- ]
142
- openshift_namespaces.run(False, thread_pool_size=1)
143
- oc = self.oc_clients[c1]
144
- oc.delete_project.assert_not_called()
145
- oc.new_project.assert_not_called()
146
-
147
- def test_dup_present_namespace_some_deletes_should_error(self):
148
- self.test_ns = [
149
- NS(c1, n1, delete=False, exists=True),
150
- NS(c1, n1, delete=True, exists=True),
151
- NS(c1, n1, delete=True, exists=True),
152
- NS(c1, n2, delete=False, exists=True),
153
- ]
154
- f = io.StringIO()
155
- with self.assertRaises(SystemExit), contextlib.redirect_stderr(f):
156
- openshift_namespaces.run(False, thread_pool_size=1)
157
- self.assertIn("Found multiple definitions", f.getvalue())
158
-
159
- oc = self.oc_clients[c1]
160
- oc.delete_project.assert_not_called()
161
- oc.new_project.assert_not_called()
162
-
163
- def test_dup_present_namespace_all_deletes_should_delete(self):
164
- self.test_ns = [
165
- NS(c1, n1, delete=True, exists=True),
166
- NS(c1, n1, delete=True, exists=True),
167
- NS(c1, n1, delete=True, exists=True),
168
- ]
169
- openshift_namespaces.run(False, thread_pool_size=1)
170
- oc = self.oc_clients[c1]
171
- oc.delete_project.assert_called()
172
- oc.new_project.assert_not_called()
173
-
174
- def test_dup_absent_namespace_no_deletes_should_create(self):
175
- self.test_ns = [
176
- NS(c1, n1, delete=False, exists=False),
177
- NS(c1, n1, delete=False, exists=False),
178
- NS(c1, n1, delete=False, exists=False),
179
- ]
180
- openshift_namespaces.run(False, thread_pool_size=1)
181
- oc = self.oc_clients[c1]
182
- oc.delete_project.assert_not_called()
183
- oc.new_project.assert_called()
184
-
185
- def test_dup_absent_namespace_some_deletes_should_error(self):
186
- self.test_ns = [
187
- NS(c1, n1, delete=True, exists=False),
188
- NS(c1, n1, delete=False, exists=False),
189
- NS(c1, n1, delete=False, exists=False),
190
- NS(c1, n2, delete=False, exists=True),
191
- ]
192
-
193
- f = io.StringIO()
194
- with self.assertRaises(SystemExit), contextlib.redirect_stderr(f):
195
- openshift_namespaces.run(False, thread_pool_size=1)
196
- self.assertIn("Found multiple definitions", f.getvalue())
197
-
198
- oc = self.oc_clients[c1]
199
- oc.delete_project.assert_not_called()
200
- oc.new_project.assert_not_called()
201
-
202
- def test_dup_absent_namespace_all_deletes_should_do_nothing(self):
203
- self.test_ns = [
204
- NS(c1, n1, delete=True, exists=False),
205
- NS(c1, n1, delete=True, exists=False),
206
- NS(c1, n1, delete=True, exists=False),
207
- ]
208
- openshift_namespaces.run(False, thread_pool_size=1)
209
- oc = self.oc_clients[c1]
210
- oc.delete_project.assert_not_called()
211
- oc.new_project.assert_not_called()
212
-
213
- def test_delete_absent_namespace(self):
214
- self.test_ns = [
215
- NS(c1, n1, delete=True, exists=False),
216
- ]
217
- openshift_namespaces.run(False, thread_pool_size=1)
218
-
219
- oc = self.oc_clients[c1]
220
- oc.delete_project.assert_not_called()
221
- oc.new_project.assert_not_called()
222
-
223
- def test_error_handling_project_exists(self):
224
- oc = self.oc_clients.setdefault(c1, Mock(name=f"oc_{c1}"))
225
- oc.project_exists.side_effect = StatusCodeError("SomeError")
226
- self.oc_map.get.return_value = oc
227
-
228
- self.test_ns = [
229
- NS(c1, "project_raises_exception", delete=True, exists=False),
230
- ]
231
- f = io.StringIO()
232
- with self.assertRaises(SystemExit), contextlib.redirect_stderr(f):
233
- openshift_namespaces.run(False, thread_pool_size=1)
234
- self.assertIn("SomeError", f.getvalue())
235
-
236
- def test_run_with_cluster_name(self):
237
- self.test_ns = [
238
- NS(c1, n1, delete=False, exists=False),
239
- NS(c2, n2, delete=False, exists=False),
240
- ]
241
-
242
- openshift_namespaces.run(False, thread_pool_size=1, cluster_name=c1)
243
-
244
- self.oc_clients[c1].new_project.assert_called_with(n1)
245
- self.assertNotIn(c2, self.oc_clients)
246
-
247
- def test_run_with_namespace_name(self):
248
- self.test_ns = [
249
- NS(c1, n1, delete=False, exists=False),
250
- NS(c2, n2, delete=False, exists=False),
251
- ]
252
-
253
- openshift_namespaces.run(False, thread_pool_size=1, namespace_name=n1)
254
-
255
- self.oc_clients[c1].new_project.assert_called_with(n1)
256
- self.assertNotIn(c2, self.oc_clients)
@@ -1,443 +0,0 @@
1
- import pytest
2
-
3
- from reconcile.utils.openshift_resource import (
4
- ConstructResourceError,
5
- ResourceInventory,
6
- ResourceNotManagedError,
7
- build_secret,
8
- )
9
- from reconcile.utils.openshift_resource import OpenshiftResource as OR
10
- from reconcile.utils.semver_helper import make_semver
11
-
12
- from .fixtures import Fixtures
13
-
14
- fxt = Fixtures("openshift_resource")
15
-
16
- TEST_INT = "test_openshift_resources"
17
- TEST_INT_VER = make_semver(1, 9, 2)
18
-
19
-
20
- def build_resource(kind: str, api_version: str, name: str):
21
- body = {
22
- "kind": kind,
23
- "apiVersion": api_version,
24
- "metadata": {
25
- "name": name,
26
- },
27
- }
28
- return OR(body, "int", "int-v")
29
-
30
-
31
- #
32
- # OpenshiftResource tests
33
- #
34
- def test_obj_intersect_equal_status_depth_0_current():
35
- desired = {
36
- "kind": "kind",
37
- "metadata": {
38
- "name": "name",
39
- },
40
- }
41
- current = {
42
- "kind": "kind",
43
- "metadata": {
44
- "name": "name",
45
- },
46
- "status": "status",
47
- }
48
- d_item = OR(desired, TEST_INT, TEST_INT_VER)
49
- c_item = OR(current, TEST_INT, TEST_INT_VER)
50
-
51
- assert d_item == c_item
52
-
53
-
54
- def test_obj_intersect_equal_status_depth_0_desired():
55
- desired = {
56
- "kind": "kind",
57
- "metadata": {
58
- "name": "name",
59
- },
60
- "status": "nonsense",
61
- }
62
- current = {
63
- "kind": "kind",
64
- "metadata": {
65
- "name": "name",
66
- },
67
- "status": "status",
68
- }
69
- d_item = OR(desired, TEST_INT, TEST_INT_VER)
70
- c_item = OR(current, TEST_INT, TEST_INT_VER)
71
-
72
- assert d_item == c_item
73
-
74
-
75
- def test_obj_intersect_equal_status_depth_not_0():
76
- desired = {
77
- "kind": "kind",
78
- "metadata": {
79
- "name": "name",
80
- },
81
- "spec": {
82
- "status": "status",
83
- },
84
- }
85
- current = {
86
- "kind": "kind",
87
- "metadata": {
88
- "name": "name",
89
- },
90
- }
91
- d_item = OR(desired, TEST_INT, TEST_INT_VER)
92
- c_item = OR(current, TEST_INT, TEST_INT_VER)
93
-
94
- assert d_item != c_item
95
-
96
-
97
- def test_verify_valid_k8s_object():
98
- resource = fxt.get_anymarkup("valid_resource.yml")
99
- openshift_resource = OR(resource, TEST_INT, TEST_INT_VER)
100
-
101
- assert openshift_resource.verify_valid_k8s_object() is None
102
-
103
-
104
- def test_verify_valid_k8s_object_false():
105
- resource = fxt.get_anymarkup("invalid_resource.yml")
106
-
107
- with pytest.raises(ConstructResourceError):
108
- openshift_resource = OR(resource, TEST_INT, TEST_INT_VER)
109
- assert openshift_resource.verify_valid_k8s_object() is None
110
-
111
-
112
- def test_invalid_name_format():
113
- resource = fxt.get_anymarkup("invalid_resource_name_format.yml")
114
-
115
- with pytest.raises(ConstructResourceError):
116
- openshift_resource = OR(resource, TEST_INT, TEST_INT_VER)
117
- assert openshift_resource.verify_valid_k8s_object() is None
118
-
119
-
120
- def test_invalid_name_too_long():
121
- resource = fxt.get_anymarkup("invalid_resource_name_too_long.yml")
122
-
123
- with pytest.raises(ConstructResourceError):
124
- openshift_resource = OR(resource, TEST_INT, TEST_INT_VER)
125
- assert openshift_resource.verify_valid_k8s_object() is None
126
-
127
-
128
- def test_invalid_container_name_format():
129
- resource = fxt.get_anymarkup("invalid_resource_container_name_format.yml")
130
-
131
- with pytest.raises(ConstructResourceError):
132
- openshift_resource = OR(resource, TEST_INT, TEST_INT_VER)
133
- assert openshift_resource.verify_valid_k8s_object() is None
134
-
135
-
136
- def test_invalid_container_name_too_long():
137
- resource = fxt.get_anymarkup("invalid_resource_container_name_too_long.yml")
138
-
139
- with pytest.raises(ConstructResourceError):
140
- openshift_resource = OR(resource, TEST_INT, TEST_INT_VER)
141
- assert openshift_resource.verify_valid_k8s_object() is None
142
-
143
-
144
- def test_annotates_resource():
145
- resource = fxt.get_anymarkup("annotates_resource.yml")
146
- openshift_resource = OR(resource, TEST_INT, TEST_INT_VER)
147
-
148
- assert openshift_resource.has_qontract_annotations() is False
149
-
150
- annotated = openshift_resource.annotate()
151
- assert annotated.has_qontract_annotations() is True
152
-
153
-
154
- def test_sha256sum_properly_ignores_some_params():
155
- resources = fxt.get_anymarkup("ignores_params.yml")
156
-
157
- assert (
158
- OR(resources[0], TEST_INT, TEST_INT_VER).annotate().sha256sum()
159
- == OR(resources[1], TEST_INT, TEST_INT_VER).annotate().sha256sum()
160
- )
161
-
162
-
163
- def test_sha256sum():
164
- resource = fxt.get_anymarkup("sha256sum.yml")
165
-
166
- openshift_resource = OR(resource, TEST_INT, TEST_INT_VER)
167
-
168
- assert (
169
- openshift_resource.sha256sum()
170
- == "1366d8ef31f0d83419d25b446e61008b16348b9efee2216873856c49cede6965"
171
- )
172
-
173
- annotated = openshift_resource.annotate()
174
-
175
- assert (
176
- annotated.sha256sum()
177
- == "1366d8ef31f0d83419d25b446e61008b16348b9efee2216873856c49cede6965"
178
- )
179
-
180
- assert annotated.has_valid_sha256sum()
181
-
182
- annotated.body["metadata"]["annotations"]["qontract.sha256sum"] = "test"
183
-
184
- assert (
185
- annotated.sha256sum()
186
- == "1366d8ef31f0d83419d25b446e61008b16348b9efee2216873856c49cede6965"
187
- )
188
-
189
- assert not annotated.has_valid_sha256sum()
190
-
191
-
192
- def test_has_owner_reference_true():
193
- resource = {
194
- "kind": "kind",
195
- "metadata": {"name": "resource", "ownerReferences": [{"name": "owner"}]},
196
- }
197
- openshift_resource = OR(resource, TEST_INT, TEST_INT_VER)
198
- assert openshift_resource.has_owner_reference()
199
-
200
-
201
- def test_has_owner_reference_false():
202
- resource = {"kind": "kind", "metadata": {"name": "resource"}}
203
- openshift_resource = OR(resource, TEST_INT, TEST_INT_VER)
204
- assert not openshift_resource.has_owner_reference()
205
-
206
-
207
- def test_secret_string_data():
208
- resource = {
209
- "kind": "Secret",
210
- "metadata": {"name": "resource"},
211
- "stringData": {"k": "v"},
212
- }
213
- expected = {
214
- "kind": "Secret",
215
- "metadata": {"annotations": {}, "name": "resource"},
216
- "data": {"k": "dg=="},
217
- }
218
- result = OR.canonicalize(resource)
219
- assert result == expected
220
-
221
-
222
- def test_managed_cluster_label_ignore():
223
- desired = {
224
- "apiVersion": "cluster.open-cluster-management.io/v1",
225
- "kind": "ManagedCluster",
226
- "metadata": {
227
- "labels": {
228
- "cloud": "Amazon",
229
- "vendor": "OpenShift",
230
- "cluster.open-cluster-management.io/clusterset": "default",
231
- "name": "xxx",
232
- },
233
- "name": "xxx",
234
- },
235
- "spec": {"hubAcceptsClient": True},
236
- }
237
- current = {
238
- "apiVersion": "cluster.open-cluster-management.io/v1",
239
- "kind": "ManagedCluster",
240
- "metadata": {
241
- "labels": {
242
- "cloud": "Amazon",
243
- "cluster.open-cluster-management.io/clusterset": "default",
244
- "name": "xxx",
245
- "vendor": "OpenShift",
246
- "clusterID": "yyy",
247
- "feature.open-cluster-management.io/addon-work-manager": "available",
248
- "managed-by": "platform",
249
- "openshiftVersion": "x.y.z",
250
- },
251
- "name": "xxx",
252
- },
253
- "spec": {"hubAcceptsClient": True},
254
- }
255
-
256
- d_r = OR(desired, TEST_INT, TEST_INT_VER)
257
- c_r = OR(current, TEST_INT, TEST_INT_VER)
258
- assert d_r == c_r
259
- assert d_r.sha256sum() == c_r.sha256sum()
260
-
261
-
262
- def test_build_secret():
263
- value = "value"
264
- encoded_value = "dmFsdWU="
265
- res = build_secret(
266
- name="name",
267
- integration=TEST_INT,
268
- integration_version=TEST_INT_VER,
269
- unencoded_data={
270
- "field": value,
271
- "empty": "",
272
- },
273
- )
274
-
275
- # test metadata
276
- assert res.kind == "Secret"
277
- assert res.name == "name"
278
- assert res.integration == TEST_INT
279
- assert res.integration_version == TEST_INT_VER
280
-
281
- # assert data section
282
- assert len(res.body["data"]) == 2
283
- assert res.body["data"]["field"] == encoded_value
284
- assert not res.body["data"]["empty"]
285
-
286
-
287
- def test_openshift_resource_kind_and_group():
288
- res = build_resource("Deployment", "apps/v1", "foo")
289
- assert res.kind_and_group == "Deployment.apps"
290
-
291
-
292
- def test_openshift_resource_kind_no_group():
293
- res = build_resource("Pod", "v1", "foo")
294
- assert res.kind_and_group == "Pod"
295
-
296
-
297
- #
298
- # ResourceInventory tests
299
- #
300
-
301
-
302
- def test_resource_inventory_add_desired():
303
- ri = ResourceInventory()
304
- ri.initialize_resource_type(
305
- cluster="cl", namespace="ns", resource_type="Deployment"
306
- )
307
- res = build_resource("Deployment", "apps/v1", "name")
308
- ri.add_desired_resource("cl", "ns", res)
309
-
310
- for cluster_name, namespace_name, resource_type, resource in ri:
311
- assert cluster_name == "cl"
312
- assert namespace_name == "ns"
313
- assert resource_type == "Deployment"
314
- assert resource["desired"]["name"] == res
315
- assert not resource["use_admin_token"]["name"]
316
-
317
-
318
- def test_resource_inventory_add_desired_without_registration():
319
- """
320
- test that adding a desired state fails if the type has not been
321
- registered upfront
322
- """
323
- ri = ResourceInventory()
324
- ri.initialize_resource_type(
325
- cluster="cl", namespace="ns", resource_type="ApprovedType"
326
- )
327
-
328
- with pytest.raises(KeyError):
329
- res = build_resource("AnotherType", "apps/v1", "foo")
330
- ri.add_desired_resource("cl", "ns", res)
331
-
332
-
333
- def test_resource_inventory_add_desired_with_managed_name():
334
- """
335
- test that adding a desired state succeeds if it's name is registered
336
- as being managed
337
- """
338
- ri = ResourceInventory()
339
- ri.initialize_resource_type(
340
- cluster="cl", namespace="ns", resource_type="Deployment", managed_names=["name"]
341
- )
342
-
343
- res = build_resource("Deployment", "apps/v1", "name")
344
- ri.add_desired_resource("cl", "ns", res)
345
-
346
-
347
- def test_resource_inventory_add_desired_without_managed_name():
348
- """
349
- test that adding a desired state fails if it's name is not registered
350
- as being managed
351
- """
352
- ri = ResourceInventory()
353
- ri.initialize_resource_type(
354
- cluster="cl", namespace="ns", resource_type="Deployment", managed_names=["name"]
355
- )
356
-
357
- with pytest.raises(ResourceNotManagedError):
358
- res = build_resource("Deployment", "apps/v1", "an-unmanaged-name")
359
- ri.add_desired_resource("cl", "ns", res)
360
-
361
-
362
- def test_resource_inventory_add_desired_privileged():
363
- ri = ResourceInventory()
364
- ri.initialize_resource_type(
365
- cluster="cl",
366
- namespace="ns",
367
- resource_type="Deployment",
368
- )
369
- res = build_resource("Deployment", "apps/v1", "name")
370
- ri.add_desired_resource("cl", "ns", res, privileged=True)
371
-
372
- for cluster_name, namespace_name, resource_type, resource in ri:
373
- assert cluster_name == "cl"
374
- assert namespace_name == "ns"
375
- assert resource_type == "Deployment"
376
- assert resource["desired"]["name"] == res
377
- assert resource["use_admin_token"]["name"]
378
-
379
-
380
- def test_resource_inventory_add_desired_resource_short_kind():
381
- """
382
- test that add_desired_resource uses the short kind name if the short
383
- name has been registered for the namespace
384
- """
385
- ri = ResourceInventory()
386
- ri.initialize_resource_type(
387
- cluster="cl", namespace="ns", resource_type="Deployment"
388
- )
389
- res = build_resource("Deployment", "apps/v1", "foo")
390
- ri.add_desired_resource("cl", "ns", res)
391
-
392
- assert len(list(ri)) == 1
393
-
394
- cluster_name, namespace_name, resource_type, resource = next(iter(ri))
395
- assert cluster_name == "cl"
396
- assert namespace_name == "ns"
397
- assert resource_type == "Deployment"
398
- assert resource["desired"].get("foo")
399
-
400
-
401
- def test_resource_inventory_add_desired_resource_long_kind():
402
- """
403
- test that add_desired_resource uses the long kind name if the long
404
- name has been registered for the namespace
405
- """
406
- ri = ResourceInventory()
407
- ri.initialize_resource_type(
408
- cluster="cl", namespace="ns", resource_type="Deployment.apps"
409
- )
410
- res = build_resource("Deployment", "apps/v1", "foo")
411
- ri.add_desired_resource("cl", "ns", res)
412
-
413
- assert len(list(ri)) == 1
414
-
415
- cluster_name, namespace_name, resource_type, resource = next(iter(ri))
416
- assert cluster_name == "cl"
417
- assert namespace_name == "ns"
418
- assert resource_type == "Deployment.apps"
419
- assert resource["desired"].get("foo")
420
-
421
-
422
- def test_resource_inventory_add_desired_resource_mixed_kinds():
423
- """
424
- test that add_desired_resource prefers the long kind name if both the long
425
- and short kind have been registered with the namespace
426
- """
427
- ri = ResourceInventory()
428
- ri.initialize_resource_type(
429
- cluster="cl", namespace="ns", resource_type="Deployment.apps"
430
- )
431
- ri.initialize_resource_type(
432
- cluster="cl", namespace="ns", resource_type="Deployment"
433
- )
434
- res = build_resource("Deployment", "apps/v1", "foo")
435
- ri.add_desired_resource("cl", "ns", res)
436
-
437
- assert len(list(ri)) == 2
438
-
439
- for _, _, resource_type, resource in ri:
440
- if resource_type == "Deployments.app":
441
- assert resource["desired"].get("foo")
442
- elif resource_type == "Deployment":
443
- assert len(resource["desired"]) == 0