qontract-reconcile 0.10.1rc1202__py3-none-any.whl → 0.10.2.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qontract_reconcile-0.10.2.dev1.dist-info/METADATA +500 -0
- {qontract_reconcile-0.10.1rc1202.dist-info → qontract_reconcile-0.10.2.dev1.dist-info}/RECORD +12 -130
- {qontract_reconcile-0.10.1rc1202.dist-info → qontract_reconcile-0.10.2.dev1.dist-info}/WHEEL +1 -2
- {qontract_reconcile-0.10.1rc1202.dist-info → qontract_reconcile-0.10.2.dev1.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,57 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
|
3
|
-
import pytest
|
4
|
-
from pytest_mock import MockerFixture
|
5
|
-
|
6
|
-
from reconcile.jenkins_worker_fleets import (
|
7
|
-
act,
|
8
|
-
get_current_state,
|
9
|
-
get_desired_state,
|
10
|
-
)
|
11
|
-
from reconcile.test.fixtures import Fixtures
|
12
|
-
from reconcile.utils.jenkins_api import JenkinsApi
|
13
|
-
from reconcile.utils.terrascript_aws_client import TerrascriptClient as Terrascript
|
14
|
-
|
15
|
-
fixture = Fixtures("jenkins_worker_fleets")
|
16
|
-
|
17
|
-
|
18
|
-
def test_jenkins_worker_fleets(mocker: MockerFixture, caplog):
|
19
|
-
mock_get = mocker.patch.object(JenkinsApi, "get_jcasc_config")
|
20
|
-
mock_get.return_value = fixture.get_anymarkup("jcasc-export.yml")
|
21
|
-
|
22
|
-
mock_gql = mocker.patch("reconcile.utils.gql.get_api", autospec=True)
|
23
|
-
mock_gql.return_value.get_resource.return_value = fixture.get_anymarkup(
|
24
|
-
"gql-queries.yml"
|
25
|
-
)["gql_resource"]
|
26
|
-
|
27
|
-
mock_apply = mocker.patch.object(JenkinsApi, "apply_jcasc_config")
|
28
|
-
|
29
|
-
instance = fixture.get_anymarkup("gql-queries.yml")["gql_response"]["instances"][0]
|
30
|
-
jenkins = JenkinsApi("url", "user", "password")
|
31
|
-
terrascript = Terrascript(
|
32
|
-
"jenkins-worker-fleets", "", 1, accounts=[], settings=None
|
33
|
-
)
|
34
|
-
current_state = get_current_state(jenkins)
|
35
|
-
workerFleets = instance.get("workerFleets", [])
|
36
|
-
desired_state = get_desired_state(terrascript, workerFleets)
|
37
|
-
with caplog.at_level(logging.INFO):
|
38
|
-
act(False, instance["name"], current_state, desired_state, jenkins)
|
39
|
-
mock_apply.assert_called_with(fixture.get_anymarkup("jcasc-apply.yml"))
|
40
|
-
|
41
|
-
assert sorted([rec.message for rec in caplog.records]) == sorted([
|
42
|
-
"['create_jenkins_worker_fleet', 'ci-int', 'ci-int-jenkins-worker-app-interface']",
|
43
|
-
"['delete_jenkins_worker_fleet', 'ci-int', 'ci-int-jenkins-worker-rhel8']",
|
44
|
-
"['update_jenkins_worker_fleet', 'ci-int', 'ci-int-jenkins-worker-app-sre']",
|
45
|
-
"['update_jenkins_worker_fleet', 'ci-int', 'test-remove-sshConnector-attrs']",
|
46
|
-
"['update_jenkins_worker_fleet', 'ci-int', 'test-add-sshConnector-JVMOpts']",
|
47
|
-
])
|
48
|
-
|
49
|
-
|
50
|
-
def test_jenkins_worker_fleets_error():
|
51
|
-
instance = fixture.get_anymarkup("gql-queries.yml")["gql_response"]["instances"][1]
|
52
|
-
terrascript = Terrascript(
|
53
|
-
"jenkins-worker-fleets", "", 1, accounts=[], settings=None
|
54
|
-
)
|
55
|
-
workerFleets = instance.get("workerFleets", [])
|
56
|
-
with pytest.raises(ValueError):
|
57
|
-
get_desired_state(terrascript, workerFleets)
|
@@ -1,519 +0,0 @@
|
|
1
|
-
from collections.abc import Callable, Mapping
|
2
|
-
from typing import Any
|
3
|
-
from unittest.mock import Mock
|
4
|
-
|
5
|
-
import pytest
|
6
|
-
from jira import JIRAError
|
7
|
-
from pytest_mock import MockerFixture
|
8
|
-
|
9
|
-
from reconcile.gql_definitions.jira_permissions_validator.jira_boards_for_permissions_validator import (
|
10
|
-
JiraBoardV1,
|
11
|
-
)
|
12
|
-
from reconcile.jira_permissions_validator import (
|
13
|
-
ValidationError,
|
14
|
-
board_is_valid,
|
15
|
-
get_jira_boards,
|
16
|
-
validate_boards,
|
17
|
-
)
|
18
|
-
from reconcile.test.fixtures import Fixtures
|
19
|
-
from reconcile.utils import metrics
|
20
|
-
from reconcile.utils.jira_client import IssueType, JiraClient, SecurityLevel
|
21
|
-
|
22
|
-
|
23
|
-
@pytest.fixture
|
24
|
-
def fx() -> Fixtures:
|
25
|
-
return Fixtures("jira_permissions_validator")
|
26
|
-
|
27
|
-
|
28
|
-
@pytest.fixture
|
29
|
-
def raw_fixture_data(fx: Fixtures) -> dict[str, Any]:
|
30
|
-
return fx.get_anymarkup("boards.yml")
|
31
|
-
|
32
|
-
|
33
|
-
@pytest.fixture
|
34
|
-
def query_func(
|
35
|
-
data_factory: Callable[[type[JiraBoardV1], Mapping[str, Any]], Mapping[str, Any]],
|
36
|
-
raw_fixture_data: dict[str, Any],
|
37
|
-
) -> Callable:
|
38
|
-
return lambda *args, **kwargs: {
|
39
|
-
"jira_boards": [
|
40
|
-
data_factory(JiraBoardV1, item) for item in raw_fixture_data["jira_boards"]
|
41
|
-
]
|
42
|
-
}
|
43
|
-
|
44
|
-
|
45
|
-
@pytest.fixture
|
46
|
-
def boards(query_func: Callable) -> list[JiraBoardV1]:
|
47
|
-
return get_jira_boards(query_func)
|
48
|
-
|
49
|
-
|
50
|
-
def test_jira_permissions_validator_get_jira_boards(
|
51
|
-
query_func: Callable, gql_class_factory: Callable
|
52
|
-
) -> None:
|
53
|
-
default = {
|
54
|
-
"name": "jira-board-default",
|
55
|
-
"server": {
|
56
|
-
"serverUrl": "https://jira-server.com",
|
57
|
-
"token": {"path": "vault/path/token", "field": "token"},
|
58
|
-
},
|
59
|
-
"issueResolveState": "Closed",
|
60
|
-
"severityPriorityMappings": {
|
61
|
-
"name": "major-major",
|
62
|
-
"mappings": [
|
63
|
-
{"priority": "Minor"},
|
64
|
-
{"priority": "Major"},
|
65
|
-
{"priority": "Critical"},
|
66
|
-
],
|
67
|
-
},
|
68
|
-
}
|
69
|
-
custom = {
|
70
|
-
"name": "jira-board-custom",
|
71
|
-
"server": {
|
72
|
-
"serverUrl": "https://jira-server.com",
|
73
|
-
"token": {"path": "vault/path/token", "field": "token"},
|
74
|
-
},
|
75
|
-
"issueType": "bug",
|
76
|
-
"issueResolveState": "Closed",
|
77
|
-
"issueReopenState": "Open",
|
78
|
-
"issueSecurityId": 32168,
|
79
|
-
"severityPriorityMappings": {
|
80
|
-
"name": "major-major",
|
81
|
-
"mappings": [
|
82
|
-
{"priority": "Minor"},
|
83
|
-
{"priority": "Major"},
|
84
|
-
{"priority": "Major"},
|
85
|
-
{"priority": "Critical"},
|
86
|
-
],
|
87
|
-
},
|
88
|
-
}
|
89
|
-
assert get_jira_boards(query_func) == [
|
90
|
-
gql_class_factory(JiraBoardV1, default),
|
91
|
-
gql_class_factory(JiraBoardV1, custom),
|
92
|
-
]
|
93
|
-
|
94
|
-
|
95
|
-
@pytest.mark.parametrize(
|
96
|
-
"board_is_valid, dry_run, error_returned, metric_set",
|
97
|
-
[
|
98
|
-
(0, True, False, False),
|
99
|
-
(ValidationError.CANT_CREATE_ISSUE, True, True, False),
|
100
|
-
(ValidationError.CANT_TRANSITION_ISSUES, True, True, False),
|
101
|
-
(ValidationError.INVALID_ISSUE_TYPE, True, True, False),
|
102
|
-
(ValidationError.INVALID_ISSUE_STATE, True, True, False),
|
103
|
-
(ValidationError.INVALID_SECURITY_LEVEL, True, True, False),
|
104
|
-
(ValidationError.INVALID_PRIORITY, True, True, False),
|
105
|
-
(ValidationError.PUBLIC_PROJECT_NO_SECURITY_LEVEL, True, True, False),
|
106
|
-
(ValidationError.PERMISSION_ERROR, True, True, True),
|
107
|
-
(ValidationError.PROJECT_ARCHIVED, True, True, False),
|
108
|
-
# no dry-run
|
109
|
-
(ValidationError.CANT_CREATE_ISSUE, False, False, False),
|
110
|
-
(ValidationError.PERMISSION_ERROR, False, False, True),
|
111
|
-
(ValidationError.PROJECT_ARCHIVED, False, False, False),
|
112
|
-
# test with another error
|
113
|
-
(
|
114
|
-
ValidationError.INVALID_PRIORITY | ValidationError.PERMISSION_ERROR,
|
115
|
-
True,
|
116
|
-
True,
|
117
|
-
False,
|
118
|
-
),
|
119
|
-
(
|
120
|
-
ValidationError.INVALID_PRIORITY | ValidationError.PERMISSION_ERROR,
|
121
|
-
False,
|
122
|
-
True,
|
123
|
-
False,
|
124
|
-
),
|
125
|
-
],
|
126
|
-
)
|
127
|
-
def test_jira_permissions_validator_validate_boards(
|
128
|
-
mocker: MockerFixture,
|
129
|
-
boards: list[JiraBoardV1],
|
130
|
-
secret_reader: Mock,
|
131
|
-
board_is_valid: ValidationError,
|
132
|
-
dry_run: bool,
|
133
|
-
error_returned: bool,
|
134
|
-
metric_set: bool,
|
135
|
-
) -> None:
|
136
|
-
board_is_valid_mock = mocker.patch(
|
137
|
-
"reconcile.jira_permissions_validator.board_is_valid"
|
138
|
-
)
|
139
|
-
board_is_valid_mock.return_value = board_is_valid
|
140
|
-
metrics_container_mock = mocker.create_autospec(spec=metrics.MetricsContainer)
|
141
|
-
jira_client_class = mocker.create_autospec(spec=JiraClient)
|
142
|
-
assert (
|
143
|
-
validate_boards(
|
144
|
-
metrics_container=metrics_container_mock,
|
145
|
-
secret_reader=secret_reader,
|
146
|
-
jira_client_settings=None,
|
147
|
-
jira_boards=boards,
|
148
|
-
default_issue_type="task",
|
149
|
-
default_reopen_state="new",
|
150
|
-
dry_run=dry_run,
|
151
|
-
jira_client_class=jira_client_class,
|
152
|
-
)
|
153
|
-
== error_returned
|
154
|
-
)
|
155
|
-
if metric_set:
|
156
|
-
metrics_container_mock.set_gauge.assert_called()
|
157
|
-
else:
|
158
|
-
metrics_container_mock.set_gauge.assert_not_called()
|
159
|
-
|
160
|
-
|
161
|
-
def test_jira_permissions_validator_board_is_valid_happy_path(
|
162
|
-
mocker: MockerFixture, gql_class_factory: Callable
|
163
|
-
) -> None:
|
164
|
-
board = gql_class_factory(
|
165
|
-
JiraBoardV1,
|
166
|
-
{
|
167
|
-
"name": "jira-board-default",
|
168
|
-
"server": {
|
169
|
-
"serverUrl": "https://jira-server.com",
|
170
|
-
"token": {"path": "vault/path/token", "field": "token"},
|
171
|
-
},
|
172
|
-
"issueType": "bug",
|
173
|
-
"issueResolveState": "Closed",
|
174
|
-
"issueReopenState": "Open",
|
175
|
-
"issueSecurityId": "32168",
|
176
|
-
"severityPriorityMappings": {
|
177
|
-
"name": "major-major",
|
178
|
-
"mappings": [
|
179
|
-
{"priority": "Minor"},
|
180
|
-
{"priority": "Major"},
|
181
|
-
{"priority": "Critical"},
|
182
|
-
],
|
183
|
-
},
|
184
|
-
},
|
185
|
-
)
|
186
|
-
jira_client = mocker.create_autospec(spec=JiraClient)
|
187
|
-
jira_client.is_archived = False
|
188
|
-
jira_client.can_create_issues.return_value = True
|
189
|
-
jira_client.can_transition_issues.return_value = True
|
190
|
-
jira_client.project_issue_types.return_value = [
|
191
|
-
IssueType(id="1", name="task", statuses=["open", "closed"]),
|
192
|
-
IssueType(id="2", name="bug", statuses=["open", "closed"]),
|
193
|
-
]
|
194
|
-
jira_client.security_levels.return_value = [
|
195
|
-
SecurityLevel(id="32168", name="foo"),
|
196
|
-
SecurityLevel(id="1", name="bar"),
|
197
|
-
]
|
198
|
-
jira_client.project_priority_scheme.return_value = ["1", "2", "3"]
|
199
|
-
assert board_is_valid(
|
200
|
-
jira=jira_client,
|
201
|
-
board=board,
|
202
|
-
default_issue_type="task",
|
203
|
-
default_reopen_state="new",
|
204
|
-
jira_server_priorities={"Minor": "1", "Major": "2", "Critical": "3"},
|
205
|
-
public_projects=[],
|
206
|
-
) == ValidationError(0)
|
207
|
-
|
208
|
-
|
209
|
-
def test_jira_permissions_validator_board_is_valid_all_errors(
|
210
|
-
mocker: MockerFixture, gql_class_factory: Callable
|
211
|
-
) -> None:
|
212
|
-
board = gql_class_factory(
|
213
|
-
JiraBoardV1,
|
214
|
-
{
|
215
|
-
"name": "jira-board-default",
|
216
|
-
"server": {
|
217
|
-
"serverUrl": "https://jira-server.com",
|
218
|
-
"token": {"path": "vault/path/token", "field": "token"},
|
219
|
-
},
|
220
|
-
"issueType": "bug",
|
221
|
-
"issueResolveState": "Closed",
|
222
|
-
"issueReopenState": "Open",
|
223
|
-
"issueSecurityId": "32168",
|
224
|
-
"severityPriorityMappings": {
|
225
|
-
"name": "major-major",
|
226
|
-
"mappings": [
|
227
|
-
{"priority": "Minor"},
|
228
|
-
{"priority": "Major"},
|
229
|
-
{"priority": "Critical"},
|
230
|
-
],
|
231
|
-
},
|
232
|
-
},
|
233
|
-
)
|
234
|
-
jira_client = mocker.create_autospec(spec=JiraClient)
|
235
|
-
jira_client.is_archived = False
|
236
|
-
jira_client.can_create_issues.return_value = False
|
237
|
-
jira_client.can_transition_issues.return_value = False
|
238
|
-
jira_client.project_issue_types.return_value = []
|
239
|
-
jira_client.security_levels.return_value = [
|
240
|
-
SecurityLevel(id="1", name="bar"),
|
241
|
-
]
|
242
|
-
jira_client.project_priority_scheme.return_value = ["1", "2"]
|
243
|
-
assert (
|
244
|
-
board_is_valid(
|
245
|
-
jira=jira_client,
|
246
|
-
board=board,
|
247
|
-
default_issue_type="task",
|
248
|
-
default_reopen_state="new",
|
249
|
-
jira_server_priorities={"Minor": "1", "Major": "2", "Critical": "3"},
|
250
|
-
public_projects=[],
|
251
|
-
)
|
252
|
-
== ValidationError.CANT_CREATE_ISSUE
|
253
|
-
| ValidationError.CANT_TRANSITION_ISSUES
|
254
|
-
| ValidationError.INVALID_ISSUE_TYPE
|
255
|
-
| ValidationError.INVALID_ISSUE_STATE
|
256
|
-
| ValidationError.INVALID_SECURITY_LEVEL
|
257
|
-
| ValidationError.INVALID_PRIORITY
|
258
|
-
)
|
259
|
-
|
260
|
-
|
261
|
-
def test_jira_permissions_validator_board_is_valid_bad_issue_status(
|
262
|
-
mocker: MockerFixture, gql_class_factory: Callable
|
263
|
-
) -> None:
|
264
|
-
board = gql_class_factory(
|
265
|
-
JiraBoardV1,
|
266
|
-
{
|
267
|
-
"name": "jira-board-default",
|
268
|
-
"server": {
|
269
|
-
"serverUrl": "https://jira-server.com",
|
270
|
-
"token": {"path": "vault/path/token", "field": "token"},
|
271
|
-
},
|
272
|
-
"issueType": "bug",
|
273
|
-
"issueResolveState": "Closed",
|
274
|
-
"issueReopenState": "Open",
|
275
|
-
"issueSecurityId": "32168",
|
276
|
-
"severityPriorityMappings": {
|
277
|
-
"name": "major-major",
|
278
|
-
"mappings": [
|
279
|
-
{"priority": "Minor"},
|
280
|
-
{"priority": "Major"},
|
281
|
-
{"priority": "Critical"},
|
282
|
-
],
|
283
|
-
},
|
284
|
-
},
|
285
|
-
)
|
286
|
-
jira_client = mocker.create_autospec(spec=JiraClient)
|
287
|
-
jira_client.is_archived = False
|
288
|
-
jira_client.can_create_issues.return_value = True
|
289
|
-
jira_client.can_transition_issues.return_value = True
|
290
|
-
jira_client.project_issue_types.return_value = [
|
291
|
-
IssueType(id="1", name="task", statuses=["not - open", "closed"]),
|
292
|
-
IssueType(id="2", name="bug", statuses=["not - open", "closed"]),
|
293
|
-
]
|
294
|
-
jira_client.security_levels.return_value = [
|
295
|
-
SecurityLevel(id="32168", name="foo"),
|
296
|
-
SecurityLevel(id="1", name="bar"),
|
297
|
-
]
|
298
|
-
jira_client.project_priority_scheme.return_value = ["1", "2", "3"]
|
299
|
-
assert (
|
300
|
-
board_is_valid(
|
301
|
-
jira=jira_client,
|
302
|
-
board=board,
|
303
|
-
default_issue_type="task",
|
304
|
-
default_reopen_state="new",
|
305
|
-
jira_server_priorities={"Minor": "1", "Major": "2", "Critical": "3"},
|
306
|
-
public_projects=[],
|
307
|
-
)
|
308
|
-
== ValidationError.INVALID_ISSUE_STATE
|
309
|
-
)
|
310
|
-
|
311
|
-
|
312
|
-
def test_jira_permissions_validator_board_is_valid_public_project(
|
313
|
-
mocker: MockerFixture, gql_class_factory: Callable
|
314
|
-
) -> None:
|
315
|
-
board = gql_class_factory(
|
316
|
-
JiraBoardV1,
|
317
|
-
{
|
318
|
-
"name": "jira-board-default",
|
319
|
-
"server": {
|
320
|
-
"serverUrl": "https://jira-server.com",
|
321
|
-
"token": {"path": "vault/path/token", "field": "token"},
|
322
|
-
},
|
323
|
-
"issueType": "bug",
|
324
|
-
"issueResolveState": "Closed",
|
325
|
-
"issueReopenState": "Open",
|
326
|
-
"issueSecurityId": None,
|
327
|
-
"severityPriorityMappings": {
|
328
|
-
"name": "major-major",
|
329
|
-
"mappings": [
|
330
|
-
{"priority": "Minor"},
|
331
|
-
{"priority": "Major"},
|
332
|
-
{"priority": "Critical"},
|
333
|
-
],
|
334
|
-
},
|
335
|
-
},
|
336
|
-
)
|
337
|
-
jira_client = mocker.create_autospec(spec=JiraClient)
|
338
|
-
jira_client.is_archived = False
|
339
|
-
jira_client.can_create_issues.return_value = True
|
340
|
-
jira_client.can_transition_issues.return_value = True
|
341
|
-
jira_client.project_issue_types.return_value = [
|
342
|
-
IssueType(id="1", name="task", statuses=["open", "closed"]),
|
343
|
-
IssueType(id="2", name="bug", statuses=["open", "closed"]),
|
344
|
-
]
|
345
|
-
jira_client.security_levels.return_value = [
|
346
|
-
SecurityLevel(id="32168", name="foo"),
|
347
|
-
SecurityLevel(id="1", name="bar"),
|
348
|
-
]
|
349
|
-
jira_client.project_priority_scheme.return_value = ["1", "2", "3"]
|
350
|
-
assert (
|
351
|
-
board_is_valid(
|
352
|
-
jira=jira_client,
|
353
|
-
board=board,
|
354
|
-
default_issue_type="task",
|
355
|
-
default_reopen_state="new",
|
356
|
-
jira_server_priorities={"Minor": "1", "Major": "2", "Critical": "3"},
|
357
|
-
public_projects=["jira-board-default"],
|
358
|
-
)
|
359
|
-
== ValidationError.PUBLIC_PROJECT_NO_SECURITY_LEVEL
|
360
|
-
)
|
361
|
-
|
362
|
-
|
363
|
-
def test_jira_permissions_validator_board_is_valid_permission_error(
|
364
|
-
mocker: MockerFixture, gql_class_factory: Callable
|
365
|
-
) -> None:
|
366
|
-
board = gql_class_factory(
|
367
|
-
JiraBoardV1,
|
368
|
-
{
|
369
|
-
"name": "jira-board-default",
|
370
|
-
"server": {
|
371
|
-
"serverUrl": "https://jira-server.com",
|
372
|
-
"token": {"path": "vault/path/token", "field": "token"},
|
373
|
-
},
|
374
|
-
"issueType": "bug",
|
375
|
-
"issueResolveState": "Closed",
|
376
|
-
"issueReopenState": "Open",
|
377
|
-
"issueSecurityId": "32168",
|
378
|
-
"severityPriorityMappings": {
|
379
|
-
"name": "major-major",
|
380
|
-
"mappings": [
|
381
|
-
{"priority": "Minor"},
|
382
|
-
{"priority": "Major"},
|
383
|
-
{"priority": "Critical"},
|
384
|
-
],
|
385
|
-
},
|
386
|
-
},
|
387
|
-
)
|
388
|
-
jira_client = mocker.create_autospec(spec=JiraClient)
|
389
|
-
jira_client.is_archived = False
|
390
|
-
jira_client.can_create_issues.side_effect = JIRAError(status_code=403)
|
391
|
-
assert (
|
392
|
-
board_is_valid(
|
393
|
-
jira=jira_client,
|
394
|
-
board=board,
|
395
|
-
default_issue_type="task",
|
396
|
-
default_reopen_state="new",
|
397
|
-
jira_server_priorities={"Minor": "1", "Major": "2", "Critical": "3"},
|
398
|
-
public_projects=[],
|
399
|
-
)
|
400
|
-
== ValidationError.PERMISSION_ERROR
|
401
|
-
)
|
402
|
-
|
403
|
-
|
404
|
-
def test_jira_permissions_validator_board_is_valid_exception(
|
405
|
-
mocker: MockerFixture, gql_class_factory: Callable
|
406
|
-
) -> None:
|
407
|
-
board = gql_class_factory(
|
408
|
-
JiraBoardV1,
|
409
|
-
{
|
410
|
-
"name": "jira-board-default",
|
411
|
-
"server": {
|
412
|
-
"serverUrl": "https://jira-server.com",
|
413
|
-
"token": {"path": "vault/path/token", "field": "token"},
|
414
|
-
},
|
415
|
-
"issueType": "bug",
|
416
|
-
"issueResolveState": "Closed",
|
417
|
-
"issueReopenState": "Open",
|
418
|
-
"issueSecurityId": "32168",
|
419
|
-
"severityPriorityMappings": {
|
420
|
-
"name": "major-major",
|
421
|
-
"mappings": [
|
422
|
-
{"priority": "Minor"},
|
423
|
-
{"priority": "Major"},
|
424
|
-
{"priority": "Critical"},
|
425
|
-
],
|
426
|
-
},
|
427
|
-
},
|
428
|
-
)
|
429
|
-
jira_client = mocker.create_autospec(spec=JiraClient)
|
430
|
-
jira_client.is_archived = False
|
431
|
-
jira_client.can_create_issues.side_effect = JIRAError(status_code=500)
|
432
|
-
with pytest.raises(JIRAError):
|
433
|
-
board_is_valid(
|
434
|
-
jira=jira_client,
|
435
|
-
board=board,
|
436
|
-
default_issue_type="task",
|
437
|
-
default_reopen_state="new",
|
438
|
-
jira_server_priorities={"Minor": "1", "Major": "2", "Critical": "3"},
|
439
|
-
public_projects=[],
|
440
|
-
)
|
441
|
-
|
442
|
-
|
443
|
-
def test_jira_permissions_validator_board_is_valid_exception_401(
|
444
|
-
mocker: MockerFixture, gql_class_factory: Callable
|
445
|
-
) -> None:
|
446
|
-
board = gql_class_factory(
|
447
|
-
JiraBoardV1,
|
448
|
-
{
|
449
|
-
"name": "jira-board-default",
|
450
|
-
"server": {
|
451
|
-
"serverUrl": "https://jira-server.com",
|
452
|
-
"token": {"path": "vault/path/token", "field": "token"},
|
453
|
-
},
|
454
|
-
"issueType": "bug",
|
455
|
-
"issueResolveState": "Closed",
|
456
|
-
"issueReopenState": "Open",
|
457
|
-
"issueSecurityId": "32168",
|
458
|
-
"severityPriorityMappings": {
|
459
|
-
"name": "major-major",
|
460
|
-
"mappings": [
|
461
|
-
{"priority": "Minor"},
|
462
|
-
{"priority": "Major"},
|
463
|
-
{"priority": "Critical"},
|
464
|
-
],
|
465
|
-
},
|
466
|
-
},
|
467
|
-
)
|
468
|
-
jira_client = mocker.create_autospec(spec=JiraClient)
|
469
|
-
jira_client.is_archived = False
|
470
|
-
jira_client.can_create_issues.side_effect = JIRAError(status_code=401)
|
471
|
-
# no error for 401
|
472
|
-
board_is_valid(
|
473
|
-
jira=jira_client,
|
474
|
-
board=board,
|
475
|
-
default_issue_type="task",
|
476
|
-
default_reopen_state="new",
|
477
|
-
jira_server_priorities={"Minor": "1", "Major": "2", "Critical": "3"},
|
478
|
-
public_projects=[],
|
479
|
-
)
|
480
|
-
|
481
|
-
|
482
|
-
def test_jira_permissions_validator_board_is_valid_archived(
|
483
|
-
mocker: MockerFixture, gql_class_factory: Callable
|
484
|
-
) -> None:
|
485
|
-
board = gql_class_factory(
|
486
|
-
JiraBoardV1,
|
487
|
-
{
|
488
|
-
"name": "jira-board-default",
|
489
|
-
"server": {
|
490
|
-
"serverUrl": "https://jira-server.com",
|
491
|
-
"token": {"path": "vault/path/token", "field": "token"},
|
492
|
-
},
|
493
|
-
"issueType": "bug",
|
494
|
-
"issueResolveState": "Closed",
|
495
|
-
"issueReopenState": "Open",
|
496
|
-
"issueSecurityId": "32168",
|
497
|
-
"severityPriorityMappings": {
|
498
|
-
"name": "major-major",
|
499
|
-
"mappings": [
|
500
|
-
{"priority": "Minor"},
|
501
|
-
{"priority": "Major"},
|
502
|
-
{"priority": "Critical"},
|
503
|
-
],
|
504
|
-
},
|
505
|
-
},
|
506
|
-
)
|
507
|
-
jira_client = mocker.create_autospec(spec=JiraClient)
|
508
|
-
jira_client.is_archived = True
|
509
|
-
assert (
|
510
|
-
board_is_valid(
|
511
|
-
jira=jira_client,
|
512
|
-
board=board,
|
513
|
-
default_issue_type="task",
|
514
|
-
default_reopen_state="new",
|
515
|
-
jira_server_priorities={"Minor": "1", "Major": "2", "Critical": "3"},
|
516
|
-
public_projects=[],
|
517
|
-
)
|
518
|
-
== ValidationError.PROJECT_ARCHIVED
|
519
|
-
)
|
reconcile/test/test_jump_host.py
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from typing import Any
|
3
|
-
from unittest.mock import create_autospec
|
4
|
-
|
5
|
-
import pytest
|
6
|
-
|
7
|
-
from reconcile.utils import gql
|
8
|
-
from reconcile.utils.jump_host import (
|
9
|
-
JumpHostBase,
|
10
|
-
JumphostParameters,
|
11
|
-
JumpHostSSH,
|
12
|
-
)
|
13
|
-
|
14
|
-
EXPECTED_USER = "test-user"
|
15
|
-
EXPECTED_HOSTNAME = "test"
|
16
|
-
EXPECTED_KNOWN_HOSTS_PATH = "path/to/known-hosts"
|
17
|
-
EXPECTED_KNOWN_HOSTS_CONTENT = "known-hosts-file-content"
|
18
|
-
|
19
|
-
|
20
|
-
@pytest.mark.parametrize(
|
21
|
-
"parameters, expected_port",
|
22
|
-
[
|
23
|
-
(
|
24
|
-
# Jumphost with default port
|
25
|
-
JumphostParameters(
|
26
|
-
hostname=EXPECTED_HOSTNAME,
|
27
|
-
key="ABC",
|
28
|
-
known_hosts=EXPECTED_KNOWN_HOSTS_PATH,
|
29
|
-
local_port=None,
|
30
|
-
port=None,
|
31
|
-
remote_port=None,
|
32
|
-
user=EXPECTED_USER,
|
33
|
-
),
|
34
|
-
22,
|
35
|
-
),
|
36
|
-
(
|
37
|
-
# Jumphost with non-default port
|
38
|
-
JumphostParameters(
|
39
|
-
hostname=EXPECTED_HOSTNAME,
|
40
|
-
key="ABC",
|
41
|
-
known_hosts=EXPECTED_KNOWN_HOSTS_PATH,
|
42
|
-
local_port=None,
|
43
|
-
port=25,
|
44
|
-
remote_port=None,
|
45
|
-
user=EXPECTED_USER,
|
46
|
-
),
|
47
|
-
25,
|
48
|
-
),
|
49
|
-
],
|
50
|
-
)
|
51
|
-
def test_base_jumphost(fs: Any, parameters: JumphostParameters, expected_port: int):
|
52
|
-
jumphost = JumpHostBase(parameters=parameters)
|
53
|
-
assert os.path.exists(jumphost._identity_file)
|
54
|
-
|
55
|
-
with open(jumphost._identity_file, encoding="locale") as f:
|
56
|
-
assert f.read() == parameters.key
|
57
|
-
|
58
|
-
assert jumphost._port == expected_port
|
59
|
-
assert jumphost._user == EXPECTED_USER
|
60
|
-
assert jumphost._hostname == EXPECTED_HOSTNAME
|
61
|
-
|
62
|
-
|
63
|
-
@pytest.mark.parametrize(
|
64
|
-
"parameters, local_port, remote_port",
|
65
|
-
[
|
66
|
-
(
|
67
|
-
# Jumphost without remote or local port set
|
68
|
-
JumphostParameters(
|
69
|
-
hostname=EXPECTED_HOSTNAME,
|
70
|
-
key="ABC",
|
71
|
-
known_hosts=EXPECTED_KNOWN_HOSTS_PATH,
|
72
|
-
local_port=None,
|
73
|
-
port=None,
|
74
|
-
remote_port=None,
|
75
|
-
user=EXPECTED_USER,
|
76
|
-
),
|
77
|
-
None,
|
78
|
-
None,
|
79
|
-
),
|
80
|
-
(
|
81
|
-
# Jumphost with remote and local port
|
82
|
-
JumphostParameters(
|
83
|
-
hostname=EXPECTED_HOSTNAME,
|
84
|
-
key="ABC",
|
85
|
-
known_hosts=EXPECTED_KNOWN_HOSTS_PATH,
|
86
|
-
local_port=25,
|
87
|
-
port=None,
|
88
|
-
remote_port=30,
|
89
|
-
user=EXPECTED_USER,
|
90
|
-
),
|
91
|
-
25,
|
92
|
-
30,
|
93
|
-
),
|
94
|
-
],
|
95
|
-
)
|
96
|
-
def test_ssh_jumphost(
|
97
|
-
fs: Any,
|
98
|
-
parameters: JumphostParameters,
|
99
|
-
local_port: int | None,
|
100
|
-
remote_port: int | None,
|
101
|
-
):
|
102
|
-
gql_mock = create_autospec(spec=gql.GqlApi)
|
103
|
-
gql_mock.get_resource.side_effect = [{"content": EXPECTED_KNOWN_HOSTS_CONTENT}]
|
104
|
-
jumphost = JumpHostSSH(parameters=parameters, gql_api=gql_mock)
|
105
|
-
known_hosts_file = jumphost._identity_dir + "/known_hosts"
|
106
|
-
|
107
|
-
assert os.path.exists(known_hosts_file)
|
108
|
-
assert jumphost._remote_port == remote_port
|
109
|
-
assert isinstance(jumphost._local_port, int)
|
110
|
-
if local_port:
|
111
|
-
assert jumphost._local_port == local_port
|
112
|
-
|
113
|
-
with open(known_hosts_file, encoding="locale") as f:
|
114
|
-
assert f.read() == EXPECTED_KNOWN_HOSTS_CONTENT
|