qontract-reconcile 0.10.1rc1201__py3-none-any.whl → 0.10.2.dev1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. qontract_reconcile-0.10.2.dev1.dist-info/METADATA +500 -0
  2. {qontract_reconcile-0.10.1rc1201.dist-info → qontract_reconcile-0.10.2.dev1.dist-info}/RECORD +14 -132
  3. {qontract_reconcile-0.10.1rc1201.dist-info → qontract_reconcile-0.10.2.dev1.dist-info}/WHEEL +1 -2
  4. {qontract_reconcile-0.10.1rc1201.dist-info → qontract_reconcile-0.10.2.dev1.dist-info}/entry_points.txt +1 -0
  5. reconcile/aws_account_manager/README.md +5 -0
  6. reconcile/change_owners/README.md +34 -0
  7. reconcile/external_resources/manager.py +12 -1
  8. reconcile/external_resources/model.py +11 -0
  9. reconcile/glitchtip/README.md +150 -0
  10. reconcile/gql_definitions/introspection.json +51176 -0
  11. reconcile/run_integration.py +293 -0
  12. reconcile/utils/binary.py +2 -2
  13. reconcile/utils/mr/README.md +198 -0
  14. reconcile/utils/oc_map.py +2 -2
  15. tools/qontract_cli.py +0 -0
  16. qontract_reconcile-0.10.1rc1201.dist-info/METADATA +0 -64
  17. qontract_reconcile-0.10.1rc1201.dist-info/top_level.txt +0 -3
  18. reconcile/test/__init__.py +0 -0
  19. reconcile/test/conftest.py +0 -157
  20. reconcile/test/fixtures.py +0 -24
  21. reconcile/test/saas_auto_promotions_manager/__init__.py +0 -0
  22. reconcile/test/saas_auto_promotions_manager/conftest.py +0 -170
  23. reconcile/test/saas_auto_promotions_manager/merge_request_manager/__init__.py +0 -0
  24. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/__init__.py +0 -0
  25. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py +0 -115
  26. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/data_keys.py +0 -19
  27. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_desired_state.py +0 -66
  28. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py +0 -86
  29. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_mr_parser.py +0 -352
  30. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_reconciler.py +0 -494
  31. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/__init__.py +0 -0
  32. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +0 -25
  33. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_multiple_namespaces.py +0 -37
  34. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_namespace.py +0 -81
  35. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_target.py +0 -61
  36. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_json_path_selector.py +0 -74
  37. reconcile/test/saas_auto_promotions_manager/test_integration_test.py +0 -52
  38. reconcile/test/saas_auto_promotions_manager/utils/__init__.py +0 -0
  39. reconcile/test/test_acs_notifiers.py +0 -393
  40. reconcile/test/test_acs_policies.py +0 -497
  41. reconcile/test/test_acs_rbac.py +0 -865
  42. reconcile/test/test_aggregated_list.py +0 -237
  43. reconcile/test/test_amtool.py +0 -37
  44. reconcile/test/test_aws_ami_cleanup.py +0 -230
  45. reconcile/test/test_aws_ami_share.py +0 -68
  46. reconcile/test/test_aws_cloudwatch_log_retention.py +0 -434
  47. reconcile/test/test_aws_iam_keys.py +0 -70
  48. reconcile/test/test_aws_iam_password_reset.py +0 -35
  49. reconcile/test/test_aws_support_cases_sos.py +0 -23
  50. reconcile/test/test_checkpoint.py +0 -178
  51. reconcile/test/test_cli.py +0 -41
  52. reconcile/test/test_closedbox_endpoint_monitoring.py +0 -207
  53. reconcile/test/test_dashdotdb_dora.py +0 -245
  54. reconcile/test/test_database_access_manager.py +0 -660
  55. reconcile/test/test_deadmanssnitch.py +0 -290
  56. reconcile/test/test_gabi_authorized_users.py +0 -72
  57. reconcile/test/test_gcr_mirror.py +0 -14
  58. reconcile/test/test_github_org.py +0 -156
  59. reconcile/test/test_github_repo_invites.py +0 -119
  60. reconcile/test/test_gitlab_housekeeping.py +0 -333
  61. reconcile/test/test_gitlab_labeler.py +0 -126
  62. reconcile/test/test_gitlab_members.py +0 -219
  63. reconcile/test/test_gitlab_permissions.py +0 -164
  64. reconcile/test/test_instrumented_wrappers.py +0 -18
  65. reconcile/test/test_integrations_manager.py +0 -1252
  66. reconcile/test/test_jenkins_worker_fleets.py +0 -57
  67. reconcile/test/test_jira_permissions_validator.py +0 -519
  68. reconcile/test/test_jump_host.py +0 -114
  69. reconcile/test/test_ldap_users.py +0 -125
  70. reconcile/test/test_make.py +0 -28
  71. reconcile/test/test_ocm_additional_routers.py +0 -133
  72. reconcile/test/test_ocm_clusters.py +0 -798
  73. reconcile/test/test_ocm_clusters_manifest_updates.py +0 -87
  74. reconcile/test/test_ocm_machine_pools.py +0 -1103
  75. reconcile/test/test_ocm_update_recommended_version.py +0 -145
  76. reconcile/test/test_ocm_upgrade_scheduler_org_updater.py +0 -125
  77. reconcile/test/test_openshift_base.py +0 -1269
  78. reconcile/test/test_openshift_cluster_bots.py +0 -240
  79. reconcile/test/test_openshift_namespace_labels.py +0 -344
  80. reconcile/test/test_openshift_namespaces.py +0 -256
  81. reconcile/test/test_openshift_resource.py +0 -443
  82. reconcile/test/test_openshift_resources_base.py +0 -478
  83. reconcile/test/test_openshift_saas_deploy.py +0 -188
  84. reconcile/test/test_openshift_saas_deploy_change_tester.py +0 -308
  85. reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py +0 -65
  86. reconcile/test/test_openshift_serviceaccount_tokens.py +0 -282
  87. reconcile/test/test_openshift_tekton_resources.py +0 -265
  88. reconcile/test/test_openshift_upgrade_watcher.py +0 -223
  89. reconcile/test/test_prometheus_rules_tester.py +0 -151
  90. reconcile/test/test_quay_membership.py +0 -86
  91. reconcile/test/test_quay_mirror.py +0 -172
  92. reconcile/test/test_quay_mirror_org.py +0 -82
  93. reconcile/test/test_quay_repos.py +0 -59
  94. reconcile/test/test_queries.py +0 -53
  95. reconcile/test/test_repo_owners.py +0 -47
  96. reconcile/test/test_requests_sender.py +0 -139
  97. reconcile/test/test_saasherder.py +0 -1611
  98. reconcile/test/test_saasherder_allowed_secret_paths.py +0 -125
  99. reconcile/test/test_secret_reader.py +0 -153
  100. reconcile/test/test_slack_base.py +0 -183
  101. reconcile/test/test_slack_usergroups.py +0 -785
  102. reconcile/test/test_sql_query.py +0 -316
  103. reconcile/test/test_status_board.py +0 -258
  104. reconcile/test/test_terraform_aws_route53.py +0 -29
  105. reconcile/test/test_terraform_cloudflare_dns.py +0 -117
  106. reconcile/test/test_terraform_cloudflare_resources.py +0 -408
  107. reconcile/test/test_terraform_cloudflare_users.py +0 -747
  108. reconcile/test/test_terraform_repo.py +0 -440
  109. reconcile/test/test_terraform_resources.py +0 -519
  110. reconcile/test/test_terraform_tgw_attachments.py +0 -1295
  111. reconcile/test/test_terraform_users.py +0 -152
  112. reconcile/test/test_terraform_vpc_peerings.py +0 -576
  113. reconcile/test/test_terraform_vpc_peerings_build_desired_state.py +0 -1434
  114. reconcile/test/test_three_way_diff_strategy.py +0 -131
  115. reconcile/test/test_utils_jinja2.py +0 -130
  116. reconcile/test/test_vault_replication.py +0 -534
  117. reconcile/test/test_vault_utils.py +0 -47
  118. reconcile/test/test_version_bump.py +0 -18
  119. reconcile/test/test_vpc_peerings_validator.py +0 -194
  120. reconcile/test/test_wrong_region.py +0 -78
  121. release/__init__.py +0 -0
  122. release/test_version.py +0 -50
  123. release/version.py +0 -104
  124. tools/cli_commands/test/__init__.py +0 -0
  125. tools/cli_commands/test/conftest.py +0 -332
  126. tools/cli_commands/test/test_aws_cost_report.py +0 -258
  127. tools/cli_commands/test/test_cost_management_api.py +0 -326
  128. tools/cli_commands/test/test_gpg_encrypt.py +0 -235
  129. tools/cli_commands/test/test_openshift_cost_optimization_report.py +0 -255
  130. tools/cli_commands/test/test_openshift_cost_report.py +0 -295
  131. tools/cli_commands/test/test_util.py +0 -70
  132. tools/test/__init__.py +0 -0
  133. tools/test/conftest.py +0 -77
  134. tools/test/test_app_interface_metrics_exporter.py +0 -48
  135. tools/test/test_erv2.py +0 -80
  136. tools/test/test_get_container_images.py +0 -230
  137. tools/test/test_qontract_cli.py +0 -197
  138. tools/test/test_saas_promotion_state.py +0 -187
  139. tools/test/test_sd_app_sre_alert_report.py +0 -74
  140. tools/test/test_sre_checkpoints.py +0 -79
@@ -1,86 +0,0 @@
1
- from unittest.mock import patch
2
-
3
- from reconcile import quay_membership
4
- from reconcile.utils import (
5
- config,
6
- gql,
7
- )
8
- from reconcile.utils.aggregated_list import AggregatedList
9
-
10
- from .fixtures import Fixtures
11
-
12
- fxt = Fixtures("quay_membership")
13
-
14
-
15
- def get_items_by_params(state, params):
16
- h = AggregatedList.hash_params(params)
17
- for group in state:
18
- this_h = AggregatedList.hash_params(group["params"])
19
-
20
- if h == this_h:
21
- return sorted(group["items"])
22
- return False
23
-
24
-
25
- class QuayApiMock:
26
- def __init__(self, list_team_members_response):
27
- self.list_team_members_response = list_team_members_response
28
-
29
- def list_team_members(self, team):
30
- return self.list_team_members_response[team]
31
-
32
-
33
- class TestQuayMembership:
34
- @staticmethod
35
- def setup_method(method):
36
- config.init_from_toml(fxt.path("config.toml"))
37
- gql.init_from_config(autodetect_sha=False)
38
-
39
- @staticmethod
40
- def do_current_state_test(path):
41
- fixture = fxt.get_anymarkup(path)
42
-
43
- quay_org_catalog = fixture["quay_org_catalog"]
44
- quay_org_teams = fixture["quay_org_teams"]
45
-
46
- store = {}
47
- for org_data in quay_org_catalog:
48
- name = org_data["name"]
49
- store[name] = {
50
- "api": QuayApiMock(quay_org_teams[name]),
51
- "teams": org_data["managedTeams"],
52
- }
53
-
54
- current_state = quay_membership.fetch_current_state(store)
55
- current_state = current_state.dump()
56
-
57
- expected_current_state = fixture["state"]
58
-
59
- assert len(current_state) == len(expected_current_state)
60
- for group in current_state:
61
- params = group["params"]
62
- items = sorted(group["items"])
63
- assert items == get_items_by_params(expected_current_state, params)
64
-
65
- @staticmethod
66
- def do_desired_state_test(path):
67
- fixture = fxt.get_anymarkup(path)
68
-
69
- with patch("reconcile.utils.gql.GqlApi.query") as m_gql:
70
- m_gql.return_value = fixture["gql_response"]
71
-
72
- desired_state = quay_membership.fetch_desired_state().dump()
73
-
74
- expected_desired_state = fixture["state"]
75
-
76
- assert len(desired_state) == len(expected_desired_state)
77
- for group in desired_state:
78
- params = group["params"]
79
- items = sorted(group["items"])
80
- assert items == get_items_by_params(expected_desired_state, params)
81
-
82
- def test_current_state_simple(self):
83
- self.do_current_state_test("current_state_simple.yml")
84
-
85
- def test_desired_state_simple(self):
86
- self.do_desired_state_test("desired_state_simple.yml")
@@ -1,172 +0,0 @@
1
- import os
2
- import tempfile
3
- from unittest.mock import create_autospec, patch
4
-
5
- import pytest
6
- import requests
7
-
8
- from reconcile.quay_mirror import (
9
- CONTROL_FILE_NAME,
10
- OrgKey,
11
- QuayMirror,
12
- queries,
13
- )
14
-
15
- from .fixtures import Fixtures
16
-
17
- NOW = 1662124612.995397
18
-
19
- fxt = Fixtures("quay_mirror")
20
-
21
-
22
- @patch("reconcile.utils.gql.get_api", autospec=True)
23
- @patch("reconcile.queries.get_app_interface_settings", return_value={})
24
- class TestControlFile:
25
- def test_check_compare_tags_no_control_file(self, mock_gql, mock_settings):
26
- assert QuayMirror.check_compare_tags_elapsed_time("/no-such-file", 100)
27
-
28
- @patch("time.time", return_value=NOW)
29
- def test_check_compare_tags_with_file(self, mock_gql, mock_settings, mock_time):
30
- with tempfile.NamedTemporaryFile() as fp:
31
- fp.write(str(NOW - 100.0).encode())
32
- fp.seek(0)
33
-
34
- assert QuayMirror.check_compare_tags_elapsed_time(fp.name, 10)
35
- assert not QuayMirror.check_compare_tags_elapsed_time(fp.name, 1000)
36
-
37
- def test_control_file_dir_does_not_exist(self, mock_gql, mock_settings):
38
- with pytest.raises(FileNotFoundError):
39
- QuayMirror(control_file_dir="/no-such-dir")
40
-
41
- def test_control_file_path_from_given_dir(self, mock_gql, mock_settings):
42
- with tempfile.TemporaryDirectory() as tmp_dir_name:
43
- qm = QuayMirror(control_file_dir=tmp_dir_name)
44
- assert qm.control_file_path == os.path.join(tmp_dir_name, CONTROL_FILE_NAME)
45
-
46
-
47
- @patch("reconcile.utils.gql.get_api", autospec=True)
48
- @patch("reconcile.queries.get_app_interface_settings", return_value={})
49
- @patch("time.time", return_value=NOW)
50
- class TestIsCompareTags:
51
- def setup_method(self):
52
- self.tmp_dir = (
53
- tempfile.TemporaryDirectory() # pylint: disable=consider-using-with
54
- )
55
- with open(
56
- os.path.join(self.tmp_dir.name, CONTROL_FILE_NAME), "w", encoding="locale"
57
- ) as fh:
58
- fh.write(str(NOW - 100.0))
59
-
60
- def teardown_method(self):
61
- self.tmp_dir.cleanup()
62
-
63
- # Last run was in NOW - 100s, we run compare tags every 10s.
64
- def test_is_compare_tags_elapsed(self, mock_gql, mock_settings, mock_time):
65
- qm = QuayMirror(control_file_dir=self.tmp_dir.name, compare_tags_interval=10)
66
- assert qm.is_compare_tags
67
-
68
- # Same as before, but now we force no compare with the option.
69
- def test_is_compare_tags_force_no_compare(self, mock_gql, mock_settings, mock_time):
70
- qm = QuayMirror(
71
- control_file_dir=self.tmp_dir.name,
72
- compare_tags_interval=10,
73
- compare_tags=False,
74
- )
75
- assert not qm.is_compare_tags
76
-
77
- # Last run was in NOW - 100s, we run compare tags every 1000s.
78
- def test_is_compare_tags_not_elapsed(self, mock_gql, mock_settings, mock_time):
79
- qm = QuayMirror(control_file_dir=self.tmp_dir.name, compare_tags_interval=1000)
80
- assert not qm.is_compare_tags
81
-
82
- # Same as before, but now we force compare with the option.
83
- def test_is_compare_tags_force_compare(self, mock_gql, mock_settings, mock_time):
84
- qm = QuayMirror(
85
- control_file_dir=self.tmp_dir.name,
86
- compare_tags_interval=1000,
87
- compare_tags=True,
88
- )
89
- assert qm.is_compare_tags
90
-
91
-
92
- @pytest.mark.parametrize(
93
- "tags, tags_exclude, candidate, result",
94
- [
95
- # Tags include tests.
96
- (["^sha256-.+sig$", "^main-.+"], None, "main-755781cc", True),
97
- (["^sha256-.+sig$", "^main-.+"], None, "sha256-8b5.sig", True),
98
- (["^sha256-.+sig$", "^main-.+"], None, "1.2.3", False),
99
- # # Tags exclude tests.
100
- (None, ["^sha256-.+sig$", "^main-.+"], "main-755781cc", False),
101
- (None, ["^sha256-.+sig$", "^main-.+"], "sha256-8b5.sig", False),
102
- (None, ["^sha256-.+sig$", "^main-.+"], "1.2.3", True),
103
- # When both includes and excludes are explicitly given, exclude take precedence.
104
- (["^sha256-.+sig$", "^main-.+"], ["main-755781cc"], "main-755781cc", False),
105
- (["^sha256-.+sig$", "^main-.+"], ["main-755781cc"], "sha256-8b5.sig", True),
106
- # both include and exclude are not set
107
- (None, None, "main-755781cc", True),
108
- ],
109
- )
110
- def test_sync_tag(tags, tags_exclude, candidate, result):
111
- assert QuayMirror.sync_tag(tags, tags_exclude, candidate) == result
112
-
113
-
114
- def test_process_repos_query_ok(mocker):
115
- repos_query = mocker.patch.object(queries, "get_quay_repos")
116
- repos_query.return_value = fxt.get_anymarkup("get_quay_repos_ok.yaml")
117
-
118
- cloudservices = OrgKey(instance="quay.io", org_name="cloudservices")
119
- app_sre = OrgKey(instance="quay.io", org_name="app-sre")
120
- session = create_autospec(requests.Session)
121
- timeout = 30
122
-
123
- summary = QuayMirror.process_repos_query()
124
- assert len(summary) == 2
125
- assert len(summary[cloudservices]) == 2
126
- assert len(summary[app_sre]) == 1
127
-
128
- mosquitto = "docker.io/library/eclipse-mosquitto"
129
- redis = "docker.io/redis"
130
-
131
- summary = QuayMirror.process_repos_query(
132
- repository_urls=[mosquitto, redis],
133
- session=session,
134
- timeout=timeout,
135
- )
136
- cl = summary[cloudservices]
137
- ap = summary[app_sre]
138
- assert len(cl) == 2
139
- assert len(ap) == 0
140
- assert cl[0]["mirror"]["url"] == mosquitto
141
- assert cl[1]["mirror"]["url"] == redis
142
-
143
- summary = QuayMirror.process_repos_query(
144
- exclude_repository_urls=[mosquitto, redis],
145
- session=session,
146
- timeout=timeout,
147
- )
148
- cl = summary[cloudservices]
149
- ap = summary[app_sre]
150
- assert len(cl) == 0
151
- assert len(summary[app_sre]) == 1
152
-
153
-
154
- def test_process_repos_query_public_dockerhub(mocker, caplog):
155
- repos_query = mocker.patch.object(queries, "get_quay_repos")
156
- repos_query.return_value = fxt.get_anymarkup("get_quay_repos_public_dockerhub.yaml")
157
-
158
- with pytest.raises(SystemExit):
159
- QuayMirror.process_repos_query()
160
-
161
- assert "can't be mirrored to a public quay repository" in caplog.text
162
-
163
-
164
- def test_quay_mirror_session(mocker):
165
- mocker.patch("reconcile.quay_mirror.gql")
166
- mocker.patch("reconcile.quay_mirror.queries")
167
- mocked_request = mocker.patch("reconcile.quay_mirror.requests")
168
-
169
- with QuayMirror() as quay_mirror:
170
- assert quay_mirror.session == mocked_request.Session.return_value
171
-
172
- mocked_request.Session.return_value.close.assert_called_once_with()
@@ -1,82 +0,0 @@
1
- import os
2
- import tempfile
3
- from unittest.mock import patch
4
-
5
- import pytest
6
-
7
- from reconcile.quay_mirror_org import (
8
- CONTROL_FILE_NAME,
9
- QuayMirrorOrg,
10
- )
11
-
12
- NOW = 1662124612.995397
13
-
14
-
15
- @patch("reconcile.utils.gql.get_api", autospec=True)
16
- @patch("reconcile.queries.get_app_interface_settings", return_value={})
17
- class TestControlFile:
18
- def test_control_file_dir_does_not_exist(self, mock_gql, mock_settings):
19
- with pytest.raises(FileNotFoundError):
20
- QuayMirrorOrg(control_file_dir="/no-such-dir")
21
-
22
- def test_control_file_path_from_given_dir(self, mock_gql, mock_settings):
23
- with tempfile.TemporaryDirectory() as tmp_dir_name:
24
- qm = QuayMirrorOrg(control_file_dir=tmp_dir_name)
25
- assert qm.control_file_path == os.path.join(tmp_dir_name, CONTROL_FILE_NAME)
26
-
27
-
28
- @patch("reconcile.utils.gql.get_api", autospec=True)
29
- @patch("reconcile.queries.get_app_interface_settings", return_value={})
30
- @patch("time.time", return_value=NOW)
31
- class TestIsCompareTags:
32
- def setup_method(self):
33
- self.tmp_dir = (
34
- tempfile.TemporaryDirectory() # pylint: disable=consider-using-with
35
- )
36
- with open(
37
- os.path.join(self.tmp_dir.name, CONTROL_FILE_NAME), "w", encoding="locale"
38
- ) as fh:
39
- fh.write(str(NOW - 100.0))
40
-
41
- def teardown_method(self):
42
- self.tmp_dir.cleanup()
43
-
44
- # Last run was in NOW - 100s, we run compare tags every 10s.
45
- def test_is_compare_tags_elapsed(self, mock_gql, mock_settings, mock_time):
46
- qm = QuayMirrorOrg(control_file_dir=self.tmp_dir.name, compare_tags_interval=10)
47
- assert qm.is_compare_tags
48
-
49
- # Same as before, but now we force no compare with the option.
50
- def test_is_compare_tags_force_no_compare(self, mock_gql, mock_settings, mock_time):
51
- qm = QuayMirrorOrg(
52
- control_file_dir=self.tmp_dir.name,
53
- compare_tags_interval=10,
54
- compare_tags=False,
55
- )
56
- assert not qm.is_compare_tags
57
-
58
- # Last run was in NOW - 100s, we run compare tags every 1000s.
59
- def test_is_compare_tags_not_elapsed(self, mock_gql, mock_settings, mock_time):
60
- qm = QuayMirrorOrg(
61
- control_file_dir=self.tmp_dir.name, compare_tags_interval=1000
62
- )
63
- assert not qm.is_compare_tags
64
-
65
- # Same as before, but now we force compare with the option.
66
- def test_is_compare_tags_force_compare(self, mock_gql, mock_settings, mock_time):
67
- qm = QuayMirrorOrg(
68
- control_file_dir=self.tmp_dir.name,
69
- compare_tags_interval=1000,
70
- compare_tags=True,
71
- )
72
- assert qm.is_compare_tags
73
-
74
-
75
- def test_quay_mirror_org_session(mocker):
76
- mocker.patch("reconcile.quay_mirror_org.get_quay_api_store")
77
- mocked_request = mocker.patch("reconcile.quay_mirror_org.requests")
78
-
79
- with QuayMirrorOrg() as quay_mirror_org:
80
- assert quay_mirror_org.session == mocked_request.Session.return_value
81
-
82
- mocked_request.Session.return_value.close.assert_called_once_with()
@@ -1,59 +0,0 @@
1
- from unittest.mock import patch
2
-
3
- from reconcile.quay_base import OrgKey
4
- from reconcile.quay_repos import (
5
- RepoInfo,
6
- act,
7
- )
8
-
9
- from .fixtures import Fixtures
10
-
11
- fxt = Fixtures("quay_repos")
12
-
13
-
14
- def build_state(fixture_state):
15
- return [
16
- RepoInfo(
17
- org_key=OrgKey("instance", "org"),
18
- name=item[0],
19
- public=item[1],
20
- description=item[2],
21
- )
22
- for item in fixture_state
23
- ]
24
-
25
-
26
- def get_test_repo_from_state(state, name):
27
- for item in state:
28
- if item.name == name:
29
- return item
30
- return None
31
-
32
-
33
- class TestQuayRepos:
34
- @staticmethod
35
- @patch("reconcile.quay_repos.act_public")
36
- @patch("reconcile.quay_repos.act_description")
37
- @patch("reconcile.quay_repos.act_delete")
38
- @patch("reconcile.quay_repos.act_create")
39
- def test_act(act_create, act_delete, act_description, act_public):
40
- fixture = fxt.get_anymarkup("state.yml")
41
-
42
- current_state = build_state(fixture["current_state"])
43
- desired_state = build_state(fixture["desired_state"])
44
-
45
- quay_api_store = {}
46
- dry_run = True
47
- act(dry_run, quay_api_store, current_state, desired_state)
48
-
49
- repo_delete = get_test_repo_from_state(current_state, "repo_delete")
50
- act_delete.assert_called_once_with(dry_run, quay_api_store, repo_delete)
51
-
52
- repo_create = get_test_repo_from_state(desired_state, "repo_create")
53
- act_create.assert_called_once_with(dry_run, quay_api_store, repo_create)
54
-
55
- repo_desc = get_test_repo_from_state(desired_state, "repo_desc")
56
- act_description.assert_called_once_with(dry_run, quay_api_store, repo_desc)
57
-
58
- repo_public = get_test_repo_from_state(desired_state, "repo_public")
59
- act_public.assert_called_once_with(dry_run, quay_api_store, repo_public)
@@ -1,53 +0,0 @@
1
- from copy import deepcopy
2
- from typing import Any
3
- from unittest.mock import (
4
- create_autospec,
5
- patch,
6
- )
7
-
8
- from reconcile import queries
9
- from reconcile.utils import gql
10
-
11
- from .fixtures import Fixtures
12
-
13
-
14
- class TestQueries:
15
- def setup_method(self) -> None:
16
- """This starts a patch on gql.query method which will answer with the
17
- contents of self.fixture_data."""
18
-
19
- # Resetting this to make sure it is set from every test
20
- self.fixture_data: dict[str, Any] = {}
21
-
22
- self.gql_patcher = patch.object(gql, "get_api", autospec=True)
23
- self.gql = self.gql_patcher.start()
24
- gqlapi_mock = create_autospec(gql.GqlApi)
25
- self.gql.return_value = gqlapi_mock
26
- gqlapi_mock.query.side_effect = self.mock_gql_query
27
-
28
- def teardown_method(self) -> None:
29
- """Cleanup patches created in self.setup_method"""
30
- self.gql_patcher.stop()
31
-
32
- def mock_gql_query(self, query: str) -> dict[str, Any]:
33
- return self.fixture_data
34
-
35
- def test_get_pipelines_providers_all_defaults(self) -> None:
36
- data = Fixtures("queries").get_json("pipelines_providers_all_defaults.json")
37
- self.fixture_data = deepcopy(data)
38
- pps = queries.get_pipelines_providers()
39
-
40
- for k in ["retention", "taskTemplates", "pipelineTemplates", "deployResources"]:
41
- assert data["pipelines_providers"][0]["defaults"][k] == pps[0][k]
42
-
43
- def test_get_pipelines_providers_mixed(self) -> None:
44
- data = Fixtures("queries").get_json("pipelines_providers_mixed.json")
45
- self.fixture_data = deepcopy(data)
46
- pps = queries.get_pipelines_providers()
47
-
48
- # the fixture has some keys overriden from the defaults
49
- for k in ["taskTemplates", "pipelineTemplates"]:
50
- assert data["pipelines_providers"][0]["defaults"][k] == pps[0][k]
51
-
52
- for k in ["retention", "deployResources"]:
53
- assert data["pipelines_providers"][0][k] == pps[0][k]
@@ -1,47 +0,0 @@
1
- from reconcile.utils import repo_owners
2
-
3
-
4
- def test_repo_owners_subpath() -> None:
5
- def _mock_get_owners_map():
6
- return {
7
- "/foo": {
8
- "approvers": ["foo_approver"],
9
- "reviewers": ["foo_reviewer"],
10
- },
11
- "/foobar": {
12
- "approvers": ["foobar_approver"],
13
- "reviewers": ["foobar_reviewer"],
14
- },
15
- "/bar": {
16
- "approvers": ["bar_approver"],
17
- "reviewers": ["bar_reviewer"],
18
- },
19
- }
20
-
21
- owners = repo_owners.RepoOwners(None)
22
- owners._get_owners_map = _mock_get_owners_map # type: ignore
23
- assert owners.get_path_owners("/foobar/baz") == {
24
- "approvers": ["foobar_approver"],
25
- "reviewers": ["foobar_reviewer"],
26
- }
27
-
28
-
29
- def test_repo_owners_subpath_closest() -> None:
30
- def _mock_get_owners_map():
31
- return {
32
- "/": {
33
- "approvers": ["root_approver"],
34
- "reviewers": ["root_reviewer"],
35
- },
36
- "/foo": {
37
- "approvers": ["foo_approver"],
38
- "reviewers": ["foo_reviewer"],
39
- },
40
- }
41
-
42
- owners = repo_owners.RepoOwners(None)
43
- owners._get_owners_map = _mock_get_owners_map # type: ignore
44
- assert owners.get_path_closest_owners("/foobar/baz") == {
45
- "approvers": ["root_approver"],
46
- "reviewers": ["root_reviewer"],
47
- }
@@ -1,139 +0,0 @@
1
- import os
2
- import sys
3
- from subprocess import CalledProcessError
4
- from unittest import TestCase
5
- from unittest.mock import patch
6
-
7
- import reconcile.requests_sender as integ
8
- from reconcile import (
9
- queries,
10
- typed_queries,
11
- )
12
-
13
-
14
- class TestRunInteg(TestCase):
15
- def setUp(self):
16
- os.environ["APP_INTERFACE_STATE_BUCKET_ACCOUNT"] = "anaccount"
17
- self.user = {
18
- "org_username": "myorg",
19
- "public_gpg_key": "mykey",
20
- }
21
-
22
- self.requests = [
23
- {
24
- "user": self.user,
25
- "credentials": "credentials_name",
26
- "name": "aname",
27
- }
28
- ]
29
-
30
- self.exit_patcher = patch.object(sys, "exit", autospec=True)
31
- self.get_encrypted_creds_patcher = patch.object(
32
- integ, "get_encrypted_credentials"
33
- )
34
- self.smtpclient_patcher = patch.object(integ, "SmtpClient", autospec=True)
35
- self.get_settings_patcher = patch.object(
36
- queries, "get_app_interface_settings", autospec=True
37
- )
38
- self.get_smtp_credentials_patcher = patch.object(
39
- integ, "get_smtp_server_connection", autospec=True
40
- )
41
- self.smtp_settings_patcher = patch.object(
42
- typed_queries.smtp, "settings", autospec=True
43
- )
44
- self.get_aws_accounts_patcher = patch.object(
45
- queries, "get_aws_accounts", autospec=True
46
- )
47
- self.get_credentials_requests_patcher = patch.object(
48
- queries, "get_credentials_requests", autospec=True
49
- )
50
- self.state_patcher = patch.object(integ, "init_state", autospec=True)
51
- self.vault_settings_patcher = patch.object(
52
- integ,
53
- "get_app_interface_vault_settings",
54
- autospec=True,
55
- )
56
-
57
- self.do_exit = self.exit_patcher.start()
58
- self.get_encrypted_credentials = self.get_encrypted_creds_patcher.start()
59
- self.smtpclient = self.smtpclient_patcher.start()
60
- self.get_app_interface_settings = self.get_settings_patcher.start()
61
- self.get_smtp_credentials = self.get_smtp_credentials_patcher.start()
62
- self.smtp_settings = self.smtp_settings_patcher.start()
63
- self.get_aws_accounts = self.get_aws_accounts_patcher.start()
64
- self.get_credentials_requests = self.get_credentials_requests_patcher.start()
65
- self.get_credentials_requests.return_value = self.requests
66
- self.get_encrypted_credentials.return_value = "anencryptedcred"
67
- self.state = self.state_patcher.start()
68
- self.vault_settings_patcher.start()
69
- self.settings = {
70
- "smtp": {
71
- "secret_path": "asecretpath",
72
- "server": "aserver",
73
- "password": "apassword",
74
- "port": 993,
75
- "require_tls": True,
76
- "username": "asmtpuser",
77
- }
78
- }
79
- self.get_app_interface_settings.return_value = self.settings
80
- self.get_aws_accounts.return_value = ["anaccount"]
81
-
82
- def tearDown(self):
83
- for p in (
84
- self.exit_patcher,
85
- self.get_encrypted_creds_patcher,
86
- self.smtpclient_patcher,
87
- self.get_settings_patcher,
88
- self.get_smtp_credentials_patcher,
89
- self.smtp_settings_patcher,
90
- self.get_credentials_requests_patcher,
91
- self.get_aws_accounts_patcher,
92
- self.state_patcher,
93
- self.vault_settings_patcher,
94
- ):
95
- p.stop()
96
-
97
- def test_valid_credentials(self):
98
- # Yeah, yeah, whatever
99
- self.state.return_value.exists.return_value = False
100
- integ.run(False)
101
- # This has succeeded
102
- self.do_exit.assert_not_called()
103
- self.get_encrypted_credentials.assert_called_once_with(
104
- "credentials_name", self.user, self.settings
105
- )
106
- calls = self.smtpclient.return_value.send_mail.call_args_list
107
- self.assertEqual(len(calls), 1)
108
- # I don't care too much about the body of the email, TBH
109
- self.assertEqual(calls[0][0][:-1], (["myorg"], "aname"))
110
- # Just check that we're still sending the encrypted credential
111
- # in the body. This assertion is backwards with regards to all
112
- # other assertions :(
113
- self.assertIn("anencryptedcred", calls[0][0][-1])
114
-
115
- def test_existing_credentials(self):
116
- self.state.return_value.exists.return_value = True
117
- integ.run(False)
118
- self.do_exit.assert_not_called()
119
- self.get_encrypted_credentials.assert_not_called()
120
- self.smtpclient.return_value.send_mail.assert_not_called()
121
-
122
- def test_invalid_credentials(self):
123
- self.get_encrypted_credentials.side_effect = CalledProcessError(
124
- stderr="iadaiada", returncode=1, cmd="a command"
125
- )
126
- self.state.return_value.exists.return_value = False
127
- integ.run(False)
128
- self.do_exit.assert_called_once()
129
- self.get_encrypted_credentials.assert_called_once()
130
- self.smtpclient.return_value.send_mail.assert_not_called()
131
-
132
- def test_dry_run_honored(self):
133
- self.state.return_value.exists.return_value = False
134
- integ.run(True)
135
-
136
- self.get_encrypted_credentials.assert_called_once()
137
- self.do_exit.assert_not_called()
138
- self.smtpclient.return_value.send_mail.assert_not_called()
139
- self.state.return_value.add.assert_not_called()