qontract-reconcile 0.10.1rc1201__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 (140) hide show
  1. qontract_reconcile-0.10.2.dev1.dist-info/METADATA +500 -0
  2. {qontract_reconcile-0.10.1rc1201.dist-info → qontract_reconcile-0.10.2.dev1.dist-info}/RECORD +14 -132
  3. {qontract_reconcile-0.10.1rc1201.dist-info → qontract_reconcile-0.10.2.dev1.dist-info}/WHEEL +1 -2
  4. {qontract_reconcile-0.10.1rc1201.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/external_resources/manager.py +12 -1
  8. reconcile/external_resources/model.py +11 -0
  9. reconcile/glitchtip/README.md +150 -0
  10. reconcile/gql_definitions/introspection.json +51176 -0
  11. reconcile/run_integration.py +293 -0
  12. reconcile/utils/binary.py +2 -2
  13. reconcile/utils/mr/README.md +198 -0
  14. reconcile/utils/oc_map.py +2 -2
  15. tools/qontract_cli.py +0 -0
  16. qontract_reconcile-0.10.1rc1201.dist-info/METADATA +0 -64
  17. qontract_reconcile-0.10.1rc1201.dist-info/top_level.txt +0 -3
  18. reconcile/test/__init__.py +0 -0
  19. reconcile/test/conftest.py +0 -157
  20. reconcile/test/fixtures.py +0 -24
  21. reconcile/test/saas_auto_promotions_manager/__init__.py +0 -0
  22. reconcile/test/saas_auto_promotions_manager/conftest.py +0 -170
  23. reconcile/test/saas_auto_promotions_manager/merge_request_manager/__init__.py +0 -0
  24. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/__init__.py +0 -0
  25. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py +0 -115
  26. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/data_keys.py +0 -19
  27. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_desired_state.py +0 -66
  28. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py +0 -86
  29. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_mr_parser.py +0 -352
  30. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_reconciler.py +0 -494
  31. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/__init__.py +0 -0
  32. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +0 -25
  33. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_multiple_namespaces.py +0 -37
  34. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_namespace.py +0 -81
  35. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_target.py +0 -61
  36. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_json_path_selector.py +0 -74
  37. reconcile/test/saas_auto_promotions_manager/test_integration_test.py +0 -52
  38. reconcile/test/saas_auto_promotions_manager/utils/__init__.py +0 -0
  39. reconcile/test/test_acs_notifiers.py +0 -393
  40. reconcile/test/test_acs_policies.py +0 -497
  41. reconcile/test/test_acs_rbac.py +0 -865
  42. reconcile/test/test_aggregated_list.py +0 -237
  43. reconcile/test/test_amtool.py +0 -37
  44. reconcile/test/test_aws_ami_cleanup.py +0 -230
  45. reconcile/test/test_aws_ami_share.py +0 -68
  46. reconcile/test/test_aws_cloudwatch_log_retention.py +0 -434
  47. reconcile/test/test_aws_iam_keys.py +0 -70
  48. reconcile/test/test_aws_iam_password_reset.py +0 -35
  49. reconcile/test/test_aws_support_cases_sos.py +0 -23
  50. reconcile/test/test_checkpoint.py +0 -178
  51. reconcile/test/test_cli.py +0 -41
  52. reconcile/test/test_closedbox_endpoint_monitoring.py +0 -207
  53. reconcile/test/test_dashdotdb_dora.py +0 -245
  54. reconcile/test/test_database_access_manager.py +0 -660
  55. reconcile/test/test_deadmanssnitch.py +0 -290
  56. reconcile/test/test_gabi_authorized_users.py +0 -72
  57. reconcile/test/test_gcr_mirror.py +0 -14
  58. reconcile/test/test_github_org.py +0 -156
  59. reconcile/test/test_github_repo_invites.py +0 -119
  60. reconcile/test/test_gitlab_housekeeping.py +0 -333
  61. reconcile/test/test_gitlab_labeler.py +0 -126
  62. reconcile/test/test_gitlab_members.py +0 -219
  63. reconcile/test/test_gitlab_permissions.py +0 -164
  64. reconcile/test/test_instrumented_wrappers.py +0 -18
  65. reconcile/test/test_integrations_manager.py +0 -1252
  66. reconcile/test/test_jenkins_worker_fleets.py +0 -57
  67. reconcile/test/test_jira_permissions_validator.py +0 -519
  68. reconcile/test/test_jump_host.py +0 -114
  69. reconcile/test/test_ldap_users.py +0 -125
  70. reconcile/test/test_make.py +0 -28
  71. reconcile/test/test_ocm_additional_routers.py +0 -133
  72. reconcile/test/test_ocm_clusters.py +0 -798
  73. reconcile/test/test_ocm_clusters_manifest_updates.py +0 -87
  74. reconcile/test/test_ocm_machine_pools.py +0 -1103
  75. reconcile/test/test_ocm_update_recommended_version.py +0 -145
  76. reconcile/test/test_ocm_upgrade_scheduler_org_updater.py +0 -125
  77. reconcile/test/test_openshift_base.py +0 -1269
  78. reconcile/test/test_openshift_cluster_bots.py +0 -240
  79. reconcile/test/test_openshift_namespace_labels.py +0 -344
  80. reconcile/test/test_openshift_namespaces.py +0 -256
  81. reconcile/test/test_openshift_resource.py +0 -443
  82. reconcile/test/test_openshift_resources_base.py +0 -478
  83. reconcile/test/test_openshift_saas_deploy.py +0 -188
  84. reconcile/test/test_openshift_saas_deploy_change_tester.py +0 -308
  85. reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py +0 -65
  86. reconcile/test/test_openshift_serviceaccount_tokens.py +0 -282
  87. reconcile/test/test_openshift_tekton_resources.py +0 -265
  88. reconcile/test/test_openshift_upgrade_watcher.py +0 -223
  89. reconcile/test/test_prometheus_rules_tester.py +0 -151
  90. reconcile/test/test_quay_membership.py +0 -86
  91. reconcile/test/test_quay_mirror.py +0 -172
  92. reconcile/test/test_quay_mirror_org.py +0 -82
  93. reconcile/test/test_quay_repos.py +0 -59
  94. reconcile/test/test_queries.py +0 -53
  95. reconcile/test/test_repo_owners.py +0 -47
  96. reconcile/test/test_requests_sender.py +0 -139
  97. reconcile/test/test_saasherder.py +0 -1611
  98. reconcile/test/test_saasherder_allowed_secret_paths.py +0 -125
  99. reconcile/test/test_secret_reader.py +0 -153
  100. reconcile/test/test_slack_base.py +0 -183
  101. reconcile/test/test_slack_usergroups.py +0 -785
  102. reconcile/test/test_sql_query.py +0 -316
  103. reconcile/test/test_status_board.py +0 -258
  104. reconcile/test/test_terraform_aws_route53.py +0 -29
  105. reconcile/test/test_terraform_cloudflare_dns.py +0 -117
  106. reconcile/test/test_terraform_cloudflare_resources.py +0 -408
  107. reconcile/test/test_terraform_cloudflare_users.py +0 -747
  108. reconcile/test/test_terraform_repo.py +0 -440
  109. reconcile/test/test_terraform_resources.py +0 -519
  110. reconcile/test/test_terraform_tgw_attachments.py +0 -1295
  111. reconcile/test/test_terraform_users.py +0 -152
  112. reconcile/test/test_terraform_vpc_peerings.py +0 -576
  113. reconcile/test/test_terraform_vpc_peerings_build_desired_state.py +0 -1434
  114. reconcile/test/test_three_way_diff_strategy.py +0 -131
  115. reconcile/test/test_utils_jinja2.py +0 -130
  116. reconcile/test/test_vault_replication.py +0 -534
  117. reconcile/test/test_vault_utils.py +0 -47
  118. reconcile/test/test_version_bump.py +0 -18
  119. reconcile/test/test_vpc_peerings_validator.py +0 -194
  120. reconcile/test/test_wrong_region.py +0 -78
  121. release/__init__.py +0 -0
  122. release/test_version.py +0 -50
  123. release/version.py +0 -104
  124. tools/cli_commands/test/__init__.py +0 -0
  125. tools/cli_commands/test/conftest.py +0 -332
  126. tools/cli_commands/test/test_aws_cost_report.py +0 -258
  127. tools/cli_commands/test/test_cost_management_api.py +0 -326
  128. tools/cli_commands/test/test_gpg_encrypt.py +0 -235
  129. tools/cli_commands/test/test_openshift_cost_optimization_report.py +0 -255
  130. tools/cli_commands/test/test_openshift_cost_report.py +0 -295
  131. tools/cli_commands/test/test_util.py +0 -70
  132. tools/test/__init__.py +0 -0
  133. tools/test/conftest.py +0 -77
  134. tools/test/test_app_interface_metrics_exporter.py +0 -48
  135. tools/test/test_erv2.py +0 -80
  136. tools/test/test_get_container_images.py +0 -230
  137. tools/test/test_qontract_cli.py +0 -197
  138. tools/test/test_saas_promotion_state.py +0 -187
  139. tools/test/test_sd_app_sre_alert_report.py +0 -74
  140. 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