qontract-reconcile 0.10.1rc1202__py3-none-any.whl → 0.10.2.dev2__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.
- qontract_reconcile-0.10.2.dev2.dist-info/METADATA +500 -0
- {qontract_reconcile-0.10.1rc1202.dist-info → qontract_reconcile-0.10.2.dev2.dist-info}/RECORD +12 -130
- {qontract_reconcile-0.10.1rc1202.dist-info → qontract_reconcile-0.10.2.dev2.dist-info}/WHEEL +1 -2
- {qontract_reconcile-0.10.1rc1202.dist-info → qontract_reconcile-0.10.2.dev2.dist-info}/entry_points.txt +1 -0
- reconcile/aws_account_manager/README.md +5 -0
- reconcile/change_owners/README.md +34 -0
- reconcile/glitchtip/README.md +150 -0
- reconcile/gql_definitions/introspection.json +51176 -0
- reconcile/run_integration.py +293 -0
- reconcile/utils/binary.py +2 -2
- reconcile/utils/mr/README.md +198 -0
- reconcile/utils/oc_map.py +2 -2
- tools/qontract_cli.py +0 -0
- qontract_reconcile-0.10.1rc1202.dist-info/METADATA +0 -64
- qontract_reconcile-0.10.1rc1202.dist-info/top_level.txt +0 -3
- reconcile/test/__init__.py +0 -0
- reconcile/test/conftest.py +0 -157
- reconcile/test/fixtures.py +0 -24
- reconcile/test/saas_auto_promotions_manager/__init__.py +0 -0
- reconcile/test/saas_auto_promotions_manager/conftest.py +0 -170
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/__init__.py +0 -0
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/__init__.py +0 -0
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py +0 -115
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/data_keys.py +0 -19
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_desired_state.py +0 -66
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py +0 -86
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_mr_parser.py +0 -352
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_reconciler.py +0 -494
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/__init__.py +0 -0
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +0 -25
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_multiple_namespaces.py +0 -37
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_namespace.py +0 -81
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_target.py +0 -61
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_json_path_selector.py +0 -74
- reconcile/test/saas_auto_promotions_manager/test_integration_test.py +0 -52
- reconcile/test/saas_auto_promotions_manager/utils/__init__.py +0 -0
- reconcile/test/test_acs_notifiers.py +0 -393
- reconcile/test/test_acs_policies.py +0 -497
- reconcile/test/test_acs_rbac.py +0 -865
- reconcile/test/test_aggregated_list.py +0 -237
- reconcile/test/test_amtool.py +0 -37
- reconcile/test/test_aws_ami_cleanup.py +0 -230
- reconcile/test/test_aws_ami_share.py +0 -68
- reconcile/test/test_aws_cloudwatch_log_retention.py +0 -434
- reconcile/test/test_aws_iam_keys.py +0 -70
- reconcile/test/test_aws_iam_password_reset.py +0 -35
- reconcile/test/test_aws_support_cases_sos.py +0 -23
- reconcile/test/test_checkpoint.py +0 -178
- reconcile/test/test_cli.py +0 -41
- reconcile/test/test_closedbox_endpoint_monitoring.py +0 -207
- reconcile/test/test_dashdotdb_dora.py +0 -245
- reconcile/test/test_database_access_manager.py +0 -660
- reconcile/test/test_deadmanssnitch.py +0 -290
- reconcile/test/test_gabi_authorized_users.py +0 -72
- reconcile/test/test_gcr_mirror.py +0 -14
- reconcile/test/test_github_org.py +0 -156
- reconcile/test/test_github_repo_invites.py +0 -119
- reconcile/test/test_gitlab_housekeeping.py +0 -333
- reconcile/test/test_gitlab_labeler.py +0 -126
- reconcile/test/test_gitlab_members.py +0 -219
- reconcile/test/test_gitlab_permissions.py +0 -164
- reconcile/test/test_instrumented_wrappers.py +0 -18
- reconcile/test/test_integrations_manager.py +0 -1252
- reconcile/test/test_jenkins_worker_fleets.py +0 -57
- reconcile/test/test_jira_permissions_validator.py +0 -519
- reconcile/test/test_jump_host.py +0 -114
- reconcile/test/test_ldap_users.py +0 -125
- reconcile/test/test_make.py +0 -28
- reconcile/test/test_ocm_additional_routers.py +0 -133
- reconcile/test/test_ocm_clusters.py +0 -798
- reconcile/test/test_ocm_clusters_manifest_updates.py +0 -87
- reconcile/test/test_ocm_machine_pools.py +0 -1103
- reconcile/test/test_ocm_update_recommended_version.py +0 -145
- reconcile/test/test_ocm_upgrade_scheduler_org_updater.py +0 -125
- reconcile/test/test_openshift_base.py +0 -1269
- reconcile/test/test_openshift_cluster_bots.py +0 -240
- reconcile/test/test_openshift_namespace_labels.py +0 -344
- reconcile/test/test_openshift_namespaces.py +0 -256
- reconcile/test/test_openshift_resource.py +0 -443
- reconcile/test/test_openshift_resources_base.py +0 -478
- reconcile/test/test_openshift_saas_deploy.py +0 -188
- reconcile/test/test_openshift_saas_deploy_change_tester.py +0 -308
- reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py +0 -65
- reconcile/test/test_openshift_serviceaccount_tokens.py +0 -282
- reconcile/test/test_openshift_tekton_resources.py +0 -265
- reconcile/test/test_openshift_upgrade_watcher.py +0 -223
- reconcile/test/test_prometheus_rules_tester.py +0 -151
- reconcile/test/test_quay_membership.py +0 -86
- reconcile/test/test_quay_mirror.py +0 -172
- reconcile/test/test_quay_mirror_org.py +0 -82
- reconcile/test/test_quay_repos.py +0 -59
- reconcile/test/test_queries.py +0 -53
- reconcile/test/test_repo_owners.py +0 -47
- reconcile/test/test_requests_sender.py +0 -139
- reconcile/test/test_saasherder.py +0 -1611
- reconcile/test/test_saasherder_allowed_secret_paths.py +0 -125
- reconcile/test/test_secret_reader.py +0 -153
- reconcile/test/test_slack_base.py +0 -183
- reconcile/test/test_slack_usergroups.py +0 -785
- reconcile/test/test_sql_query.py +0 -316
- reconcile/test/test_status_board.py +0 -258
- reconcile/test/test_terraform_aws_route53.py +0 -29
- reconcile/test/test_terraform_cloudflare_dns.py +0 -117
- reconcile/test/test_terraform_cloudflare_resources.py +0 -408
- reconcile/test/test_terraform_cloudflare_users.py +0 -747
- reconcile/test/test_terraform_repo.py +0 -440
- reconcile/test/test_terraform_resources.py +0 -519
- reconcile/test/test_terraform_tgw_attachments.py +0 -1295
- reconcile/test/test_terraform_users.py +0 -152
- reconcile/test/test_terraform_vpc_peerings.py +0 -576
- reconcile/test/test_terraform_vpc_peerings_build_desired_state.py +0 -1434
- reconcile/test/test_three_way_diff_strategy.py +0 -131
- reconcile/test/test_utils_jinja2.py +0 -130
- reconcile/test/test_vault_replication.py +0 -534
- reconcile/test/test_vault_utils.py +0 -47
- reconcile/test/test_version_bump.py +0 -18
- reconcile/test/test_vpc_peerings_validator.py +0 -194
- reconcile/test/test_wrong_region.py +0 -78
- release/__init__.py +0 -0
- release/test_version.py +0 -50
- release/version.py +0 -104
- tools/cli_commands/test/__init__.py +0 -0
- tools/cli_commands/test/conftest.py +0 -332
- tools/cli_commands/test/test_aws_cost_report.py +0 -258
- tools/cli_commands/test/test_cost_management_api.py +0 -326
- tools/cli_commands/test/test_gpg_encrypt.py +0 -235
- tools/cli_commands/test/test_openshift_cost_optimization_report.py +0 -255
- tools/cli_commands/test/test_openshift_cost_report.py +0 -295
- tools/cli_commands/test/test_util.py +0 -70
- tools/test/__init__.py +0 -0
- tools/test/conftest.py +0 -77
- tools/test/test_app_interface_metrics_exporter.py +0 -48
- tools/test/test_erv2.py +0 -80
- tools/test/test_get_container_images.py +0 -230
- tools/test/test_qontract_cli.py +0 -197
- tools/test/test_saas_promotion_state.py +0 -187
- tools/test/test_sd_app_sre_alert_report.py +0 -74
- 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
|