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,265 +0,0 @@
|
|
1
|
-
# Setting ignore[misc] for setters on TstData:
|
2
|
-
# see https://github.com/python/mypy/issues/9160
|
3
|
-
# Made this a complete ignore because there are even more errors here that need
|
4
|
-
# to be addressed, but it was blocking other changes.
|
5
|
-
# type: ignore
|
6
|
-
|
7
|
-
from copy import deepcopy
|
8
|
-
from typing import Any
|
9
|
-
from unittest.mock import (
|
10
|
-
create_autospec,
|
11
|
-
patch,
|
12
|
-
)
|
13
|
-
|
14
|
-
import pytest
|
15
|
-
|
16
|
-
from reconcile import openshift_tekton_resources as otr
|
17
|
-
from reconcile.queries import PIPELINES_PROVIDERS_QUERY
|
18
|
-
from reconcile.utils import gql
|
19
|
-
|
20
|
-
from .fixtures import Fixtures
|
21
|
-
|
22
|
-
MODULE = "reconcile.openshift_tekton_resources"
|
23
|
-
|
24
|
-
|
25
|
-
class TstUnsupportedGqlQueryError(Exception):
|
26
|
-
pass
|
27
|
-
|
28
|
-
|
29
|
-
class TstData:
|
30
|
-
"""Class to add data to tests in setUp. It will be used by mocks"""
|
31
|
-
|
32
|
-
def __init__(self):
|
33
|
-
self._providers = []
|
34
|
-
self._saas_files = []
|
35
|
-
|
36
|
-
@property
|
37
|
-
def providers(self) -> list[dict[str, Any]]:
|
38
|
-
return self._providers
|
39
|
-
|
40
|
-
@property
|
41
|
-
def saas_files(self) -> list[dict[str, Any]]:
|
42
|
-
return self._saas_files
|
43
|
-
|
44
|
-
@providers.setter
|
45
|
-
def providers(self, providers: list[dict[str, Any]]) -> None:
|
46
|
-
if not isinstance(providers, list):
|
47
|
-
raise TypeError(f"Expecting list, have {type(providers)}")
|
48
|
-
self._providers = providers
|
49
|
-
|
50
|
-
@saas_files.setter
|
51
|
-
def saas_files(self, saas_files: list[dict[str, Any]]) -> None:
|
52
|
-
if not isinstance(saas_files, list):
|
53
|
-
raise TypeError(f"Expecting list, have {type(saas_files)}")
|
54
|
-
self._saas_files = saas_files
|
55
|
-
|
56
|
-
|
57
|
-
# This was originally written in unittest, hence the use of xunit-style
|
58
|
-
# setup/teardown methods instead of pytest fixtures.
|
59
|
-
class TestOpenshiftTektonResources:
|
60
|
-
@staticmethod
|
61
|
-
def _test_deploy_resources_in_task(
|
62
|
-
desired_resources, task_name, deploy_resources
|
63
|
-
) -> None:
|
64
|
-
"""Helper method to test if deploy resources have been properly set"""
|
65
|
-
for dr in desired_resources:
|
66
|
-
if dr["name"] == task_name:
|
67
|
-
task = dr["value"].body
|
68
|
-
for step in task["spec"]["steps"]:
|
69
|
-
if step["name"] == otr.DEFAULT_DEPLOY_RESOURCES_STEP_NAME:
|
70
|
-
assert step["computeResources"] == deploy_resources
|
71
|
-
break
|
72
|
-
|
73
|
-
def mock_gql_get_resource(self, path: str) -> dict[str, str]:
|
74
|
-
"""Mock for GqlApi.get_resources using fixtures"""
|
75
|
-
content = self.fxt.get(path)
|
76
|
-
return {
|
77
|
-
"path": path,
|
78
|
-
"content": content,
|
79
|
-
"sha256sum": "",
|
80
|
-
} # we do not need it for these tests
|
81
|
-
|
82
|
-
def mock_gql_query(self, query: str) -> dict[str, Any]:
|
83
|
-
"""Mock for GqlApi.query using test_data set in setUp"""
|
84
|
-
if query == otr.SAAS_FILES_QUERY:
|
85
|
-
return {"saas_files": self.test_data.saas_files}
|
86
|
-
if query == PIPELINES_PROVIDERS_QUERY:
|
87
|
-
return {"pipelines_providers": self.test_data.providers}
|
88
|
-
raise TstUnsupportedGqlQueryError("Unsupported query")
|
89
|
-
|
90
|
-
def setup_method(self) -> None:
|
91
|
-
self.test_data = TstData()
|
92
|
-
|
93
|
-
self.fxt = Fixtures("openshift_tekton_resources")
|
94
|
-
|
95
|
-
# Common fixtures
|
96
|
-
self.saas1 = self.fxt.get_json("saas1.json")
|
97
|
-
self.saas2 = self.fxt.get_json("saas2.json")
|
98
|
-
self.saas2_wr = self.fxt.get_json("saas2-with-resources.json")
|
99
|
-
self.provider1 = self.fxt.get_json("provider1.json")
|
100
|
-
self.provider2_wr = self.fxt.get_json("provider2-with-resources.json")
|
101
|
-
|
102
|
-
# Patcher for GqlApi methods
|
103
|
-
self.gql_patcher = patch.object(gql, "get_api", autospec=True)
|
104
|
-
self.gql = self.gql_patcher.start()
|
105
|
-
gqlapi_mock = create_autospec(gql.GqlApi)
|
106
|
-
self.gql.return_value = gqlapi_mock
|
107
|
-
gqlapi_mock.query.side_effect = self.mock_gql_query
|
108
|
-
gqlapi_mock.get_resource.side_effect = self.mock_gql_get_resource
|
109
|
-
|
110
|
-
def teardown_method(self) -> None:
|
111
|
-
"""cleanup patches created in self.setUp"""
|
112
|
-
self.gql_patcher.stop()
|
113
|
-
|
114
|
-
def test_get_one_saas_file(self) -> None:
|
115
|
-
self.test_data.saas_files = [self.saas1, self.saas2]
|
116
|
-
saas_files = otr.fetch_saas_files(self.saas1["name"])
|
117
|
-
assert saas_files == [self.saas1]
|
118
|
-
|
119
|
-
def test_fetch_tkn_providers(self) -> None:
|
120
|
-
self.test_data.saas_files = [self.saas1, self.saas2]
|
121
|
-
self.test_data.providers = [self.provider1, self.provider2_wr]
|
122
|
-
|
123
|
-
tkn_providers = otr.fetch_tkn_providers(None)
|
124
|
-
keys_expected = {self.provider1["name"], self.provider2_wr["name"]}
|
125
|
-
assert tkn_providers.keys() == keys_expected
|
126
|
-
|
127
|
-
def test_duplicate_providers(self) -> None:
|
128
|
-
self.test_data.saas_files = [self.saas1]
|
129
|
-
provider1_duplicate = deepcopy(self.provider1)
|
130
|
-
self.test_data.providers = [self.provider1, provider1_duplicate]
|
131
|
-
msg = r"There are duplicates in tekton providers names: provider1"
|
132
|
-
with pytest.raises(otr.OpenshiftTektonResourcesBadConfigError, match=msg):
|
133
|
-
otr.fetch_tkn_providers(None)
|
134
|
-
|
135
|
-
def test_fetch_desired_resources(self) -> None:
|
136
|
-
self.test_data.saas_files = [self.saas1, self.saas2, self.saas2_wr]
|
137
|
-
self.test_data.providers = [self.provider1, self.provider2_wr]
|
138
|
-
|
139
|
-
desired_resources = otr.fetch_desired_resources(otr.fetch_tkn_providers(None))
|
140
|
-
|
141
|
-
# we have one task per namespace and a pipeline + task per saas file
|
142
|
-
assert len(desired_resources) == 8
|
143
|
-
|
144
|
-
def test_fetch_desired_resources_names(self) -> None:
|
145
|
-
self.test_data.saas_files = [self.saas1]
|
146
|
-
self.test_data.providers = [self.provider1]
|
147
|
-
desired_resources = otr.fetch_desired_resources(otr.fetch_tkn_providers(None))
|
148
|
-
|
149
|
-
expected_task_names = {
|
150
|
-
"o-push-gateway-openshift-saas-deploy-task-status-metric",
|
151
|
-
"o-openshift-saas-deploy-saas1",
|
152
|
-
}
|
153
|
-
expected_pipeline_name = "o-saas-deploy-saas1"
|
154
|
-
|
155
|
-
task_names = set()
|
156
|
-
for dr in desired_resources:
|
157
|
-
body = dr["value"].body
|
158
|
-
if body["kind"] == "Task":
|
159
|
-
task_names.add(body["metadata"]["name"])
|
160
|
-
else:
|
161
|
-
pipeline_name = body["metadata"]["name"]
|
162
|
-
|
163
|
-
assert task_names == expected_task_names
|
164
|
-
assert pipeline_name == expected_pipeline_name
|
165
|
-
|
166
|
-
def test_set_deploy_resources_default(self) -> None:
|
167
|
-
self.test_data.saas_files = [self.saas1]
|
168
|
-
self.test_data.providers = [self.provider1]
|
169
|
-
desired_resources = otr.fetch_desired_resources(otr.fetch_tkn_providers(None))
|
170
|
-
|
171
|
-
# we need to locate the onePerSaasFile task in the desired resources
|
172
|
-
# we could be very strict and find the onePerSaasFile task in
|
173
|
-
# self.provider1 or just use the actual structure of the fixtures
|
174
|
-
task_name = otr.build_one_per_saas_file_tkn_task_name(
|
175
|
-
template_name=self.provider1["taskTemplates"][0]["name"],
|
176
|
-
saas_file_name=self.saas1["name"],
|
177
|
-
)
|
178
|
-
self._test_deploy_resources_in_task(
|
179
|
-
desired_resources, task_name, otr.DEFAULT_DEPLOY_RESOURCES
|
180
|
-
)
|
181
|
-
|
182
|
-
def test_set_deploy_resources_from_provider(self) -> None:
|
183
|
-
self.test_data.saas_files = [self.saas2]
|
184
|
-
self.test_data.providers = [self.provider2_wr]
|
185
|
-
desired_resources = otr.fetch_desired_resources(otr.fetch_tkn_providers(None))
|
186
|
-
|
187
|
-
task_name = otr.build_one_per_saas_file_tkn_task_name(
|
188
|
-
template_name=self.provider2_wr["taskTemplates"][0]["name"],
|
189
|
-
saas_file_name=self.saas2["name"],
|
190
|
-
)
|
191
|
-
self._test_deploy_resources_in_task(
|
192
|
-
desired_resources, task_name, self.provider2_wr["deployResources"]
|
193
|
-
)
|
194
|
-
|
195
|
-
def test_set_deploy_resources_from_saas_file(self) -> None:
|
196
|
-
self.test_data.saas_files = [self.saas2_wr]
|
197
|
-
self.test_data.providers = [self.provider2_wr]
|
198
|
-
desired_resources = otr.fetch_desired_resources(otr.fetch_tkn_providers(None))
|
199
|
-
|
200
|
-
task_name = otr.build_one_per_saas_file_tkn_task_name(
|
201
|
-
template_name=self.provider2_wr["taskTemplates"][0]["name"],
|
202
|
-
saas_file_name=self.saas2["name"],
|
203
|
-
)
|
204
|
-
self._test_deploy_resources_in_task(
|
205
|
-
desired_resources, task_name, self.saas2_wr["deployResources"]
|
206
|
-
)
|
207
|
-
|
208
|
-
def test_task_templates_name_duplicates(self) -> None:
|
209
|
-
self.provider4_wtd = self.fxt.get_json("provider4-with-task-duplicates.json")
|
210
|
-
self.saas4 = self.fxt.get_json("saas4.json")
|
211
|
-
self.test_data.saas_files = [self.saas4]
|
212
|
-
self.test_data.providers = [self.provider4_wtd]
|
213
|
-
|
214
|
-
msg = (
|
215
|
-
r"There are duplicates in task templates names in tekton "
|
216
|
-
r"provider provider4-with-task-duplicates"
|
217
|
-
)
|
218
|
-
with pytest.raises(otr.OpenshiftTektonResourcesBadConfigError, match=msg):
|
219
|
-
otr.fetch_desired_resources(otr.fetch_tkn_providers(None))
|
220
|
-
|
221
|
-
def test_task_templates_unknown_task(self) -> None:
|
222
|
-
self.provider5_wut = self.fxt.get_json("provider5-with-unknown-task.json")
|
223
|
-
self.saas5 = self.fxt.get_json("saas5.json")
|
224
|
-
self.test_data.saas_files = [self.saas5]
|
225
|
-
self.test_data.providers = [self.provider5_wut]
|
226
|
-
|
227
|
-
msg = r"Unknown task this-is-an-unknown-task in pipeline template saas-deploy"
|
228
|
-
with pytest.raises(otr.OpenshiftTektonResourcesBadConfigError, match=msg):
|
229
|
-
otr.fetch_desired_resources(otr.fetch_tkn_providers(None))
|
230
|
-
|
231
|
-
@patch(f"{MODULE}.DEFAULT_DEPLOY_RESOURCES_STEP_NAME", "unknown-step")
|
232
|
-
def test_task_templates_unknown_deploy_resources_step(self) -> None:
|
233
|
-
self.test_data.saas_files = [self.saas1]
|
234
|
-
self.test_data.providers = [self.provider1]
|
235
|
-
msg = (
|
236
|
-
r"Cannot find a step named unknown-step to set resources in "
|
237
|
-
r"task template openshift-saas-deploy"
|
238
|
-
)
|
239
|
-
with pytest.raises(otr.OpenshiftTektonResourcesBadConfigError, match=msg):
|
240
|
-
otr.fetch_desired_resources(otr.fetch_tkn_providers(None))
|
241
|
-
|
242
|
-
@patch(f"{MODULE}.RESOURCE_MAX_LENGTH", 10)
|
243
|
-
def test_task_templates_resource_too_long(self) -> None:
|
244
|
-
self.test_data.saas_files = [self.saas1]
|
245
|
-
self.test_data.providers = [self.provider1]
|
246
|
-
msg = (
|
247
|
-
r"Resource name o-openshift-saas-deploy-saas1 is longer than 10 characters"
|
248
|
-
)
|
249
|
-
with pytest.raises(otr.OpenshiftTektonResourcesNameTooLongError, match=msg):
|
250
|
-
otr.fetch_desired_resources(otr.fetch_tkn_providers(None))
|
251
|
-
|
252
|
-
# This test describes a situation that should not take place in current app-interface since
|
253
|
-
# pipeline names are limited to 15 characters. But just in case, the code protects us from
|
254
|
-
# this situation to happen, hence the test.
|
255
|
-
def test_pipeline_templates_resource_too_long(self) -> None:
|
256
|
-
self.provider6_tlpn = self.fxt.get_json("provider6-too-long-pipeline-name.yaml")
|
257
|
-
self.saas6_39cn = self.fxt.get_json("saas6-39-chars-name.yaml")
|
258
|
-
self.test_data.saas_files = [self.saas6_39cn]
|
259
|
-
self.test_data.providers = [self.provider6_tlpn]
|
260
|
-
msg = (
|
261
|
-
r"Pipeline name o-saas-deploy-too-long-name-this-is-a-saas-file-with-a-39-char-name "
|
262
|
-
r"is longer than 56 characters"
|
263
|
-
)
|
264
|
-
with pytest.raises(otr.OpenshiftTektonResourcesNameTooLongError, match=msg):
|
265
|
-
otr.fetch_desired_resources(otr.fetch_tkn_providers(None))
|
@@ -1,223 +0,0 @@
|
|
1
|
-
from datetime import (
|
2
|
-
datetime,
|
3
|
-
timedelta,
|
4
|
-
)
|
5
|
-
|
6
|
-
import pytest
|
7
|
-
|
8
|
-
from reconcile import openshift_upgrade_watcher as ouw
|
9
|
-
from reconcile.gql_definitions.common.clusters import ClusterV1
|
10
|
-
from reconcile.test.fixtures import Fixtures
|
11
|
-
from reconcile.utils.models import data_default_none
|
12
|
-
|
13
|
-
fxt = Fixtures("openshift_upgrade_watcher")
|
14
|
-
|
15
|
-
|
16
|
-
def load_cluster(path: str) -> ClusterV1:
|
17
|
-
content = fxt.get_anymarkup(path)
|
18
|
-
return ClusterV1(**data_default_none(ClusterV1, content))
|
19
|
-
|
20
|
-
|
21
|
-
@pytest.fixture
|
22
|
-
def state(mocker):
|
23
|
-
return mocker.patch("reconcile.utils.state.State", autospec=True).return_value
|
24
|
-
|
25
|
-
|
26
|
-
@pytest.fixture
|
27
|
-
def slack(mocker):
|
28
|
-
return mocker.patch(
|
29
|
-
"reconcile.utils.slack_api.SlackApi", autospec=True
|
30
|
-
).return_value
|
31
|
-
|
32
|
-
|
33
|
-
cluster_name = "cluster1"
|
34
|
-
upgrade_at = datetime(2020, 6, 1, 0, 0, 0)
|
35
|
-
old_version = "4.5.1"
|
36
|
-
upgrade_version = "4.5.2"
|
37
|
-
|
38
|
-
|
39
|
-
@pytest.fixture
|
40
|
-
def ouw_oc_map(mocker):
|
41
|
-
map = mocker.patch("reconcile.utils.oc_map.OCMap", autospec=True).return_value
|
42
|
-
map.clusters.return_value = [cluster_name]
|
43
|
-
oc = mocker.patch("reconcile.utils.oc.OCNative", autospec=True)
|
44
|
-
oc.get.return_value = {"items": []}
|
45
|
-
map.get.return_value = oc
|
46
|
-
return map
|
47
|
-
|
48
|
-
|
49
|
-
@pytest.fixture
|
50
|
-
def ouw_ocm_map(mocker):
|
51
|
-
return mocker.patch("reconcile.utils.ocm.OCMMap", autospec=True)
|
52
|
-
|
53
|
-
|
54
|
-
@pytest.fixture
|
55
|
-
def upgrade_config():
|
56
|
-
return {
|
57
|
-
"items": [
|
58
|
-
{
|
59
|
-
"spec": {
|
60
|
-
"upgradeAt": upgrade_at.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
61
|
-
"desired": {"version": upgrade_version},
|
62
|
-
}
|
63
|
-
}
|
64
|
-
]
|
65
|
-
}
|
66
|
-
|
67
|
-
|
68
|
-
@pytest.fixture
|
69
|
-
def dt(mocker):
|
70
|
-
return mocker.patch(
|
71
|
-
"reconcile.openshift_upgrade_watcher.datetime",
|
72
|
-
mocker.Mock(datetime, wraps=datetime),
|
73
|
-
)
|
74
|
-
|
75
|
-
|
76
|
-
def test_new_upgrade_pending(
|
77
|
-
mocker, state, slack, ouw_oc_map, ouw_ocm_map, upgrade_config, dt
|
78
|
-
):
|
79
|
-
"""There is an UpgradeConfig on the cluster but its upgradeAt is in the future"""
|
80
|
-
dt.utcnow.return_value = upgrade_at - timedelta(hours=1)
|
81
|
-
gso = mocker.patch(
|
82
|
-
"reconcile.openshift_upgrade_watcher._get_start_osd", autospec=True
|
83
|
-
)
|
84
|
-
gso.return_value = upgrade_at.strftime("%Y-%m-%dT%H:%M:%SZ"), upgrade_version
|
85
|
-
ouw.notify_upgrades_start(
|
86
|
-
ocm_map=ouw_ocm_map,
|
87
|
-
oc_map=ouw_oc_map,
|
88
|
-
clusters=[load_cluster("cluster1.yml")],
|
89
|
-
state=state,
|
90
|
-
slack=slack,
|
91
|
-
)
|
92
|
-
assert slack.chat_post_message.call_count == 0
|
93
|
-
assert state.add.call_count == 0
|
94
|
-
|
95
|
-
|
96
|
-
def test_new_upgrade_notify(
|
97
|
-
mocker, state, slack, ouw_oc_map, ouw_ocm_map, upgrade_config, dt
|
98
|
-
):
|
99
|
-
"""There is an UpgradeConfig on the cluster, its upgradeAt is in the past,
|
100
|
-
and we did not already notify"""
|
101
|
-
dt.utcnow.return_value = upgrade_at + timedelta(hours=1)
|
102
|
-
gso = mocker.patch(
|
103
|
-
"reconcile.openshift_upgrade_watcher._get_start_osd", autospec=True
|
104
|
-
)
|
105
|
-
gso.return_value = upgrade_at.strftime("%Y-%m-%dT%H:%M:%SZ"), upgrade_version
|
106
|
-
state.exists.return_value = False
|
107
|
-
ouw.notify_upgrades_start(
|
108
|
-
ocm_map=ouw_ocm_map,
|
109
|
-
oc_map=ouw_oc_map,
|
110
|
-
clusters=[load_cluster("cluster1.yml")],
|
111
|
-
state=state,
|
112
|
-
slack=slack,
|
113
|
-
)
|
114
|
-
assert slack.chat_post_message.call_count == 1
|
115
|
-
assert state.add.call_count == 1
|
116
|
-
|
117
|
-
|
118
|
-
def test_new_upgrade_already_notified(
|
119
|
-
mocker, state, slack, ouw_oc_map, ouw_ocm_map, upgrade_config, dt
|
120
|
-
):
|
121
|
-
"""There is an UpgradeConfig on the cluster, its upgradeAt is in the past,
|
122
|
-
and we already notified"""
|
123
|
-
state.exists.return_value = True
|
124
|
-
state.get.return_value = None
|
125
|
-
dt.utcnow.return_value = upgrade_at + timedelta(hours=1)
|
126
|
-
gso = mocker.patch(
|
127
|
-
"reconcile.openshift_upgrade_watcher._get_start_osd", autospec=True
|
128
|
-
)
|
129
|
-
gso.return_value = upgrade_at.strftime("%Y-%m-%dT%H:%M:%SZ"), upgrade_version
|
130
|
-
ouw.notify_upgrades_start(
|
131
|
-
ocm_map=ouw_ocm_map,
|
132
|
-
oc_map=ouw_oc_map,
|
133
|
-
clusters=[load_cluster("cluster1.yml")],
|
134
|
-
state=state,
|
135
|
-
slack=slack,
|
136
|
-
)
|
137
|
-
assert slack.chat_post_message.call_count == 0
|
138
|
-
assert state.add.call_count == 0
|
139
|
-
|
140
|
-
|
141
|
-
@pytest.fixture
|
142
|
-
def clusters():
|
143
|
-
cluster = load_cluster("cluster1.yml")
|
144
|
-
cluster.name = cluster_name
|
145
|
-
if not cluster.spec:
|
146
|
-
raise RuntimeError("This test requires a cluster_spec. Check your fixture.")
|
147
|
-
cluster.spec.version = upgrade_version
|
148
|
-
return [cluster]
|
149
|
-
|
150
|
-
|
151
|
-
def test_new_version_no_op(mocker, state, slack, clusters):
|
152
|
-
"""We already notified for this cluster & version"""
|
153
|
-
state.exists.return_value = True
|
154
|
-
state.get.return_value = upgrade_version # same version, already notified
|
155
|
-
ouw.notify_cluster_new_version(clusters, state=state, slack=slack)
|
156
|
-
assert slack.chat_post_message.call_count == 0
|
157
|
-
assert state.add.call_count == 0
|
158
|
-
|
159
|
-
|
160
|
-
def test_new_version_no_state(mocker, state, slack, clusters):
|
161
|
-
"""We never notified for this cluster"""
|
162
|
-
state.exists.return_value = False # never notified for this cluster
|
163
|
-
state.get.return_value = None
|
164
|
-
ouw.notify_cluster_new_version(clusters, state=state, slack=slack)
|
165
|
-
assert slack.chat_post_message.call_count == 1
|
166
|
-
assert state.add.call_count == 1
|
167
|
-
|
168
|
-
|
169
|
-
def test_new_version_notify(mocker, state, slack, clusters):
|
170
|
-
"""We already notified for this cluster, but on an old version"""
|
171
|
-
state.exists.return_value = True
|
172
|
-
state.get.return_value = old_version # different version
|
173
|
-
ouw.notify_cluster_new_version(clusters, state=state, slack=slack)
|
174
|
-
assert slack.chat_post_message.call_count == 1
|
175
|
-
assert state.add.call_count == 1
|
176
|
-
|
177
|
-
|
178
|
-
def test__get_start_hypershift_started(mocker):
|
179
|
-
get_control_plane_upgrade_policies_mock = mocker.patch.object(
|
180
|
-
ouw, "get_control_plane_upgrade_policies", autospec=True
|
181
|
-
)
|
182
|
-
get_control_plane_upgrade_policies_mock.return_value = [
|
183
|
-
{
|
184
|
-
"next_run": upgrade_at,
|
185
|
-
"version": upgrade_version,
|
186
|
-
"state": "started",
|
187
|
-
}
|
188
|
-
]
|
189
|
-
ocm_api_mock = mocker.patch(
|
190
|
-
"reconcile.utils.ocm_base_client.OCMBaseClient", autospec=True
|
191
|
-
)
|
192
|
-
next_run, version = ouw._get_start_hypershift(ocm_api_mock, "cluster-id")
|
193
|
-
assert next_run == upgrade_at
|
194
|
-
assert version == upgrade_version
|
195
|
-
|
196
|
-
|
197
|
-
def test__get_start_hypershift_noop(mocker):
|
198
|
-
get_control_plane_upgrade_policies_mock = mocker.patch.object(
|
199
|
-
ouw, "get_control_plane_upgrade_policies", autospec=True
|
200
|
-
)
|
201
|
-
get_control_plane_upgrade_policies_mock.return_value = []
|
202
|
-
ocm_api_mock = mocker.patch(
|
203
|
-
"reconcile.utils.ocm_base_client.OCMBaseClient", autospec=True
|
204
|
-
)
|
205
|
-
next_run, version = ouw._get_start_hypershift(ocm_api_mock, "cluster-id")
|
206
|
-
assert not next_run
|
207
|
-
assert not version
|
208
|
-
|
209
|
-
|
210
|
-
def test__get_start_osd_no_op(ouw_oc_map):
|
211
|
-
"""There is no UpgradeConfig on the cluster"""
|
212
|
-
next_run, version = ouw._get_start_osd(ouw_oc_map, cluster_name)
|
213
|
-
assert not next_run
|
214
|
-
assert not version
|
215
|
-
|
216
|
-
|
217
|
-
def test__get_start_osd_started(ouw_oc_map, upgrade_config):
|
218
|
-
"""There is no UpgradeConfig on the cluster"""
|
219
|
-
oc = ouw_oc_map.get.return_value
|
220
|
-
oc.get.return_value = upgrade_config
|
221
|
-
next_run, version = ouw._get_start_osd(ouw_oc_map, cluster_name)
|
222
|
-
assert next_run == "2020-06-01T00:00:00Z"
|
223
|
-
assert version == "4.5.2"
|
@@ -1,151 +0,0 @@
|
|
1
|
-
from typing import Any
|
2
|
-
from unittest.mock import (
|
3
|
-
create_autospec,
|
4
|
-
patch,
|
5
|
-
)
|
6
|
-
|
7
|
-
import pytest
|
8
|
-
|
9
|
-
from reconcile.gql_definitions.common.app_interface_vault_settings import (
|
10
|
-
AppInterfaceSettingsV1,
|
11
|
-
)
|
12
|
-
from reconcile.openshift_resources_base import NAMESPACES_QUERY
|
13
|
-
from reconcile.prometheus_rules_tester.integration import Test as PTest
|
14
|
-
from reconcile.prometheus_rules_tester.integration import (
|
15
|
-
check_rules_and_tests,
|
16
|
-
run,
|
17
|
-
)
|
18
|
-
from reconcile.status import ExitCodes
|
19
|
-
from reconcile.utils import gql
|
20
|
-
|
21
|
-
from .fixtures import Fixtures
|
22
|
-
|
23
|
-
THREAD_POOL_SIZE = 2
|
24
|
-
|
25
|
-
|
26
|
-
class TstUnsupportedGqlQueryError(Exception):
|
27
|
-
pass
|
28
|
-
|
29
|
-
|
30
|
-
class TestPrometheusRulesTester:
|
31
|
-
def mock_gql_get_resource(self, path: str) -> dict[str, str]:
|
32
|
-
"""Mock for GqlApi.get_resources using fixtures. Namespace fixtures have paths
|
33
|
-
that refer to files in fixture dir so that this methos loads them."""
|
34
|
-
content = self.fxt.get(path)
|
35
|
-
return {
|
36
|
-
"path": path,
|
37
|
-
"content": content,
|
38
|
-
"sha256sum": "",
|
39
|
-
}
|
40
|
-
|
41
|
-
def mock_gql_query(self, query: str) -> dict[str, Any]:
|
42
|
-
"""Mock for GqlApi.query using test_data set in setup_method."""
|
43
|
-
if query == NAMESPACES_QUERY:
|
44
|
-
return {"namespaces": self.ns_data}
|
45
|
-
|
46
|
-
raise TstUnsupportedGqlQueryError("Unsupported query")
|
47
|
-
|
48
|
-
def setup_method(self) -> None:
|
49
|
-
self.ns_data: dict[str, Any] = {}
|
50
|
-
|
51
|
-
self.fxt = Fixtures("prometheus_rules_tester")
|
52
|
-
self.alerting_services = {"yak-shaver"}
|
53
|
-
self.vault_settings = AppInterfaceSettingsV1(vault=False)
|
54
|
-
|
55
|
-
# Patcher for GqlApi methods
|
56
|
-
self.gql_patcher = patch.object(gql, "get_api", autospec=True)
|
57
|
-
self.gql = self.gql_patcher.start()
|
58
|
-
gqlapi_mock = create_autospec(gql.GqlApi)
|
59
|
-
self.gql.return_value = gqlapi_mock
|
60
|
-
gqlapi_mock.query.side_effect = self.mock_gql_query
|
61
|
-
gqlapi_mock.get_resource.side_effect = self.mock_gql_get_resource
|
62
|
-
|
63
|
-
def teardown_method(self) -> None:
|
64
|
-
"""cleanup patches created in setup_method"""
|
65
|
-
self.gql_patcher.stop()
|
66
|
-
|
67
|
-
def run_check(self, cluster_name=None) -> list[PTest]:
|
68
|
-
return check_rules_and_tests(
|
69
|
-
vault_settings=self.vault_settings,
|
70
|
-
alerting_services=self.alerting_services,
|
71
|
-
thread_pool_size=THREAD_POOL_SIZE,
|
72
|
-
cluster_names=cluster_name,
|
73
|
-
)
|
74
|
-
|
75
|
-
def test_ok_non_templated(self) -> None:
|
76
|
-
self.ns_data = self.fxt.get_anymarkup("ns-ok-non-templated.yaml")
|
77
|
-
assert self.run_check() == []
|
78
|
-
|
79
|
-
def test_ok_templated(self) -> None:
|
80
|
-
self.ns_data = self.fxt.get_anymarkup("ns-ok-templated.yaml")
|
81
|
-
assert self.run_check() == []
|
82
|
-
|
83
|
-
# Bad rule syntax should me caught by schema, but since we check it, we test it."
|
84
|
-
def test_bad_rule(self) -> None:
|
85
|
-
self.ns_data = self.fxt.get_anymarkup("ns-bad-rule.yaml")
|
86
|
-
failed = self.run_check()
|
87
|
-
assert len(failed) == 1
|
88
|
-
assert "Error running promtool command" in str(failed[0].result)
|
89
|
-
|
90
|
-
def test_bad_alerting_service(self) -> None:
|
91
|
-
self.ns_data = self.fxt.get_anymarkup("ns-ok-templated.yaml")
|
92
|
-
self.alerting_services = {"not-a-yak-shaver"}
|
93
|
-
failed = self.run_check()
|
94
|
-
assert len(failed) == 1
|
95
|
-
assert "services are missing from alertingServices" in str(failed[0].result)
|
96
|
-
|
97
|
-
@patch("reconcile.prometheus_rules_tester.integration.MAX_CONFIGMAP_SIZE", 1)
|
98
|
-
def test_rule_too_long(self) -> None:
|
99
|
-
self.ns_data = self.fxt.get_anymarkup("ns-ok-non-templated.yaml")
|
100
|
-
failed = self.run_check()
|
101
|
-
assert len(failed) == 1
|
102
|
-
assert "Rules spec is larger than 1 bytes" in str(failed[0].result)
|
103
|
-
|
104
|
-
def test_bad_test(self) -> None:
|
105
|
-
self.ns_data = self.fxt.get_anymarkup("ns-bad-test.yaml")
|
106
|
-
failed = self.run_check()
|
107
|
-
assert len(failed) == 1
|
108
|
-
assert "Error running promtool command" in str(failed[0].result)
|
109
|
-
|
110
|
-
# Tests regarding filtering by cluster name.
|
111
|
-
def test_2_ns_bad_alerting_service_unfiltered(self) -> None:
|
112
|
-
self.ns_data = self.fxt.get_anymarkup("2-ns-ok-non-templated.yaml")
|
113
|
-
self.alerting_services = {"not-a-yak-shaver"}
|
114
|
-
assert len(self.run_check()) == 2
|
115
|
-
|
116
|
-
def test_2_ns_bad_alerting_service_filtered(self) -> None:
|
117
|
-
self.ns_data = self.fxt.get_anymarkup("2-ns-ok-non-templated.yaml")
|
118
|
-
self.alerting_services = {"not-a-yak-shaver"}
|
119
|
-
|
120
|
-
failed = self.run_check(cluster_name="appint-ex-01")
|
121
|
-
assert len(failed) == 1
|
122
|
-
|
123
|
-
failed = self.run_check(cluster_name="appint-ex-02")
|
124
|
-
assert len(failed) == 1
|
125
|
-
|
126
|
-
failed = self.run_check(cluster_name="no-such-cluster")
|
127
|
-
assert len(failed) == 0
|
128
|
-
|
129
|
-
@patch("reconcile.prometheus_rules_tester.integration.get_alerting_services")
|
130
|
-
@patch(
|
131
|
-
"reconcile.prometheus_rules_tester.integration.get_app_interface_vault_settings"
|
132
|
-
)
|
133
|
-
def test_run_logs_error(
|
134
|
-
self, mocker_vault_settings, mocker_alerting_services, caplog
|
135
|
-
) -> None:
|
136
|
-
self.ns_data = self.fxt.get_anymarkup("ns-bad-test.yaml")
|
137
|
-
mocker_alerting_services.return_value = {"yak-shaver"}
|
138
|
-
mocker_vault_settings.return_value = AppInterfaceSettingsV1(vault=False)
|
139
|
-
cluster_name = ("appint-ex-01",)
|
140
|
-
|
141
|
-
with pytest.raises(SystemExit) as exc:
|
142
|
-
run(False, THREAD_POOL_SIZE, cluster_names=cluster_name)
|
143
|
-
|
144
|
-
assert exc.value.code == ExitCodes.ERROR
|
145
|
-
|
146
|
-
error_msg = (
|
147
|
-
"Error checking rule bad-test.prometheusrules.yaml "
|
148
|
-
"from namespace openshift-customer-monitoring in "
|
149
|
-
f"cluster {cluster_name[0]}: Error running promtool command"
|
150
|
-
)
|
151
|
-
assert error_msg in caplog.text
|