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,308 +0,0 @@
|
|
1
|
-
from collections.abc import Callable
|
2
|
-
|
3
|
-
import pytest
|
4
|
-
|
5
|
-
from reconcile.openshift_saas_deploy_change_tester import (
|
6
|
-
State,
|
7
|
-
collect_compare_diffs,
|
8
|
-
collect_state,
|
9
|
-
)
|
10
|
-
from reconcile.typed_queries.saas_files import SaasFile
|
11
|
-
|
12
|
-
|
13
|
-
@pytest.fixture
|
14
|
-
def saas_files(gql_class_factory: Callable[..., SaasFile]) -> list[SaasFile]:
|
15
|
-
return [
|
16
|
-
gql_class_factory(
|
17
|
-
SaasFile,
|
18
|
-
{
|
19
|
-
"path": "/path.yml",
|
20
|
-
"name": "saas-file-name",
|
21
|
-
"app": {"name": "ccx-data-pipeline"},
|
22
|
-
"pipelinesProvider": {
|
23
|
-
"name": "pipeline-provider-01",
|
24
|
-
"provider": "tekton",
|
25
|
-
"namespace": {
|
26
|
-
"name": "namespace",
|
27
|
-
"cluster": {
|
28
|
-
"name": "appint-ex-01",
|
29
|
-
"serverUrl": "https://cluster-url",
|
30
|
-
"internal": False,
|
31
|
-
"automationToken": {"path": "creds", "field": "token"},
|
32
|
-
"consoleUrl": "https://console-url",
|
33
|
-
},
|
34
|
-
},
|
35
|
-
"defaults": {
|
36
|
-
"pipelineTemplates": {
|
37
|
-
"openshiftSaasDeploy": {"name": "saas-deploy"}
|
38
|
-
}
|
39
|
-
},
|
40
|
-
},
|
41
|
-
"deployResources": {
|
42
|
-
"requests": {"cpu": "1500m", "memory": "700Mi"},
|
43
|
-
"limits": {"cpu": "2000m", "memory": "1Gi"},
|
44
|
-
},
|
45
|
-
"managedResourceTypes": [
|
46
|
-
"Deployment",
|
47
|
-
],
|
48
|
-
"takeover": None,
|
49
|
-
"deprecated": None,
|
50
|
-
"compare": None,
|
51
|
-
"clusterAdmin": None,
|
52
|
-
"imagePatterns": [
|
53
|
-
"quay.io/some-org",
|
54
|
-
],
|
55
|
-
"allowedSecretParameterPaths": None,
|
56
|
-
"use_channel_in_image_tag": None,
|
57
|
-
"parameters": '{"SAAS_DEFAULT_1":"saas", "SAAS_DEFAULT_2":"saas"}',
|
58
|
-
"secretParameters": [
|
59
|
-
{
|
60
|
-
"name": "saas_default_1",
|
61
|
-
"secret": {
|
62
|
-
"field": "saas_field_1",
|
63
|
-
"path": "saas_path_1",
|
64
|
-
"version": 1,
|
65
|
-
},
|
66
|
-
},
|
67
|
-
{
|
68
|
-
"name": "saas_default_2",
|
69
|
-
"secret": {
|
70
|
-
"field": "saas_field_2",
|
71
|
-
"path": "saas_path_2",
|
72
|
-
"version": 1,
|
73
|
-
},
|
74
|
-
},
|
75
|
-
],
|
76
|
-
"resourceTemplates": [
|
77
|
-
{
|
78
|
-
"name": "tmpl",
|
79
|
-
"url": "https://github.com/some-org/some-repo.git",
|
80
|
-
"path": "/deploy.yaml",
|
81
|
-
"hash_length": 7,
|
82
|
-
"parameters": '{"TMPL_DEFAULT_1":"tmpl", "TMPL_DEFAULT_2":"tmpl"}', # used in collect_state but not saasherder
|
83
|
-
"secretParameters": [ # used in collect_state but saasherder
|
84
|
-
{
|
85
|
-
"name": "tmpl_default_1",
|
86
|
-
"secret": {
|
87
|
-
"field": "tmpl_field_1",
|
88
|
-
"path": "tmpl_path_1",
|
89
|
-
"version": 1,
|
90
|
-
},
|
91
|
-
},
|
92
|
-
{
|
93
|
-
"name": "tmpl_default_2",
|
94
|
-
"secret": {
|
95
|
-
"field": "tmpl_field_2",
|
96
|
-
"path": "tmpl_path_2",
|
97
|
-
"version": 1,
|
98
|
-
},
|
99
|
-
},
|
100
|
-
],
|
101
|
-
"targets": [
|
102
|
-
{
|
103
|
-
"name": "target",
|
104
|
-
"namespace": {
|
105
|
-
"name": "namespace",
|
106
|
-
"environment": {
|
107
|
-
"name": "env-name",
|
108
|
-
# used in collect_state but not saas_file_owners
|
109
|
-
"parameters": '{ "ENV_DEFAULT_1": "env", "ENV_DEFAULT_2": "env" }',
|
110
|
-
"secretParameters": [
|
111
|
-
{
|
112
|
-
"name": "env_default_1",
|
113
|
-
"secret": {
|
114
|
-
"field": "env_field_1",
|
115
|
-
"path": "env_path_1",
|
116
|
-
"version": 1,
|
117
|
-
},
|
118
|
-
},
|
119
|
-
{
|
120
|
-
"name": "env_default_2",
|
121
|
-
"secret": {
|
122
|
-
"field": "env_field_2",
|
123
|
-
"path": "env_path_2",
|
124
|
-
"version": 1,
|
125
|
-
},
|
126
|
-
},
|
127
|
-
],
|
128
|
-
},
|
129
|
-
"app": {"name": "app"},
|
130
|
-
"cluster": {"name": "cluster"},
|
131
|
-
},
|
132
|
-
"ref": "master",
|
133
|
-
"promotion": None,
|
134
|
-
"parameters": '{"TARGET":"target", "ENV_DEFAULT_1":"target", "SAAS_DEFAULT_1":"target", "TMPL_DEFAULT_1":"target"}',
|
135
|
-
"secretParameters": [
|
136
|
-
{
|
137
|
-
"name": "target_default",
|
138
|
-
"secret": {
|
139
|
-
"field": "target_field",
|
140
|
-
"path": "target_path",
|
141
|
-
"version": 1,
|
142
|
-
"format": None,
|
143
|
-
},
|
144
|
-
},
|
145
|
-
{
|
146
|
-
"name": "saas_default_1",
|
147
|
-
"secret": {
|
148
|
-
"field": "target_field",
|
149
|
-
"path": "target_path",
|
150
|
-
"version": 1,
|
151
|
-
"format": None,
|
152
|
-
},
|
153
|
-
},
|
154
|
-
{
|
155
|
-
"name": "tmpl_default_1",
|
156
|
-
"secret": {
|
157
|
-
"field": "target_field",
|
158
|
-
"path": "target_path",
|
159
|
-
"version": 1,
|
160
|
-
"format": None,
|
161
|
-
},
|
162
|
-
},
|
163
|
-
{
|
164
|
-
"name": "env_default_1",
|
165
|
-
"secret": {
|
166
|
-
"field": "target_field",
|
167
|
-
"path": "target_path",
|
168
|
-
"version": 1,
|
169
|
-
"format": None,
|
170
|
-
},
|
171
|
-
},
|
172
|
-
],
|
173
|
-
"upstream": {
|
174
|
-
"instance": {
|
175
|
-
"name": "ci",
|
176
|
-
"serverUrl": "https://ci.example.net",
|
177
|
-
},
|
178
|
-
"name": "job-name",
|
179
|
-
},
|
180
|
-
"image": None,
|
181
|
-
"disable": None,
|
182
|
-
"delete": None,
|
183
|
-
},
|
184
|
-
],
|
185
|
-
}
|
186
|
-
],
|
187
|
-
},
|
188
|
-
)
|
189
|
-
]
|
190
|
-
|
191
|
-
|
192
|
-
def test_collect_state(saas_files: list[SaasFile]) -> None:
|
193
|
-
"""
|
194
|
-
this implementation of collect_state may contain a bug when compared to the
|
195
|
-
saas_herder way to of collecting parameters and secrets.
|
196
|
-
there are 4 places where parameters and secrets can be defined with qontract-schema:
|
197
|
-
1) environment-1
|
198
|
-
2) saas-file-2
|
199
|
-
3) saas-file-2.resourceTemplates
|
200
|
-
4) saas-file-2.resourceTemplates.targets
|
201
|
-
|
202
|
-
- saas-herder collects from 1), 2), 4)
|
203
|
-
- collect_state collects from 2), 3), 4)
|
204
|
-
"""
|
205
|
-
state = collect_state(saas_files)
|
206
|
-
expected = State(**{
|
207
|
-
"saas_file_path": "/path.yml",
|
208
|
-
"saas_file_name": "saas-file-name",
|
209
|
-
"saas_file_deploy_resources": {
|
210
|
-
"requests": {"cpu": "1500m", "memory": "700Mi"},
|
211
|
-
"limits": {"cpu": "2000m", "memory": "1Gi"},
|
212
|
-
},
|
213
|
-
"resource_template_name": "tmpl",
|
214
|
-
"namespace": "namespace",
|
215
|
-
"environment": "env-name",
|
216
|
-
"cluster": "cluster",
|
217
|
-
"url": "https://github.com/some-org/some-repo.git",
|
218
|
-
"ref": "master",
|
219
|
-
"parameters": {
|
220
|
-
"SAAS_DEFAULT_1": "target",
|
221
|
-
"SAAS_DEFAULT_2": "saas",
|
222
|
-
"ENV_DEFAULT_1": "target",
|
223
|
-
# "ENV_DEFAULT_2": "env", # todo - check if it is a bug or on purpose that environment-1 params are not loaded
|
224
|
-
"TMPL_DEFAULT_1": "target",
|
225
|
-
"TMPL_DEFAULT_2": "tmpl",
|
226
|
-
"TARGET": "target",
|
227
|
-
},
|
228
|
-
"secret_parameters": {
|
229
|
-
"target_default": {
|
230
|
-
"field": "target_field",
|
231
|
-
"path": "target_path",
|
232
|
-
"version": 1,
|
233
|
-
"format": None,
|
234
|
-
},
|
235
|
-
"saas_default_1": {
|
236
|
-
"field": "target_field",
|
237
|
-
"path": "target_path",
|
238
|
-
"version": 1,
|
239
|
-
"format": None,
|
240
|
-
},
|
241
|
-
"saas_default_2": {
|
242
|
-
"field": "saas_field_2",
|
243
|
-
"path": "saas_path_2",
|
244
|
-
"version": 1,
|
245
|
-
"format": None,
|
246
|
-
},
|
247
|
-
"env_default_1": {
|
248
|
-
"field": "target_field",
|
249
|
-
"path": "target_path",
|
250
|
-
"version": 1,
|
251
|
-
"format": None,
|
252
|
-
},
|
253
|
-
# environment-1 secrets should be present since saasherder uses them but collect_state does sadly not
|
254
|
-
# "env_default_2": {
|
255
|
-
# "field": "env_field_2",
|
256
|
-
# "path": "env_path_2",
|
257
|
-
# "version": 1,
|
258
|
-
# "format": None,
|
259
|
-
# },
|
260
|
-
"tmpl_default_1": {
|
261
|
-
"field": "target_field",
|
262
|
-
"path": "target_path",
|
263
|
-
"version": 1,
|
264
|
-
"format": None,
|
265
|
-
},
|
266
|
-
"tmpl_default_2": {
|
267
|
-
"field": "tmpl_field_2",
|
268
|
-
"path": "tmpl_path_2",
|
269
|
-
"version": 1,
|
270
|
-
"format": None,
|
271
|
-
},
|
272
|
-
},
|
273
|
-
"upstream": {
|
274
|
-
"instance": {"name": "ci", "serverUrl": "https://ci.example.net"},
|
275
|
-
"name": "job-name",
|
276
|
-
},
|
277
|
-
"saas_file_definitions": {
|
278
|
-
"managed_resource_types": ["Deployment"],
|
279
|
-
"image_patterns": ["quay.io/some-org"],
|
280
|
-
"use_channel_in_image_tag": False,
|
281
|
-
},
|
282
|
-
"disable": None,
|
283
|
-
"delete": None,
|
284
|
-
"target_path": None,
|
285
|
-
})
|
286
|
-
assert state == [expected]
|
287
|
-
|
288
|
-
|
289
|
-
def test_collect_compare_diffs(saas_files: list[SaasFile]):
|
290
|
-
state_1 = collect_state(saas_files)
|
291
|
-
state_2 = [s.copy() for s in state_1]
|
292
|
-
state_1[0].ref = "another-branch"
|
293
|
-
diffs = collect_compare_diffs(
|
294
|
-
state_1, state_2, changed_paths=[state_1[0].saas_file_path]
|
295
|
-
)
|
296
|
-
assert diffs == {
|
297
|
-
"https://github.com/some-org/some-repo.git/compare/another-branch...master"
|
298
|
-
}
|
299
|
-
|
300
|
-
|
301
|
-
def test_collect_compare_diffs_other_paths(saas_files: list[SaasFile]):
|
302
|
-
state_1 = collect_state(saas_files)
|
303
|
-
state_2 = [s.copy() for s in state_1]
|
304
|
-
state_1[0].ref = "another-branch"
|
305
|
-
diffs = collect_compare_diffs(
|
306
|
-
state_1, state_2, changed_paths=["/some/other-path.yml"]
|
307
|
-
)
|
308
|
-
assert diffs == set()
|
@@ -1,65 +0,0 @@
|
|
1
|
-
from datetime import UTC, datetime
|
2
|
-
from typing import Any
|
3
|
-
|
4
|
-
import pytest
|
5
|
-
|
6
|
-
from reconcile.gql_definitions.fragments.pipeline_provider_retention import (
|
7
|
-
PipelineProviderRetention,
|
8
|
-
)
|
9
|
-
from reconcile.openshift_saas_deploy_trigger_cleaner import get_pipeline_runs_to_delete
|
10
|
-
|
11
|
-
from .fixtures import Fixtures
|
12
|
-
|
13
|
-
fxt = Fixtures("openshift_saas_deploy_trigger_cleaner")
|
14
|
-
|
15
|
-
|
16
|
-
@pytest.fixture
|
17
|
-
def now() -> datetime:
|
18
|
-
return datetime(2024, 4, 4, 0, 0, 0, 0, tzinfo=UTC)
|
19
|
-
|
20
|
-
|
21
|
-
# A fixture simulating the output of getting PipelineRuns from a namespace, simplified
|
22
|
-
# as it contains only the fields relevant for get_pipeline_runs_to_delete, reversed
|
23
|
-
# sorted by creationTimestamp
|
24
|
-
@pytest.fixture
|
25
|
-
def pipeline_runs() -> list[dict[str, Any]]:
|
26
|
-
return fxt.get_anymarkup("pipeline_runs.yaml")
|
27
|
-
|
28
|
-
|
29
|
-
# No min/max settings, we go with whatever "days" says
|
30
|
-
def test_days(now: datetime, pipeline_runs: list[dict[str, Any]]) -> None:
|
31
|
-
retention = PipelineProviderRetention(days=1, minimum=None, maximum=None)
|
32
|
-
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 4
|
33
|
-
|
34
|
-
retention = PipelineProviderRetention(days=2, minimum=None, maximum=None)
|
35
|
-
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 2
|
36
|
-
|
37
|
-
|
38
|
-
# Minimum set, it takes precedence over "days"
|
39
|
-
def test_days_and_minimum(now: datetime, pipeline_runs: list[dict[str, Any]]) -> None:
|
40
|
-
retention = PipelineProviderRetention(days=1, minimum=5, maximum=None)
|
41
|
-
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 1
|
42
|
-
# We would have removed four from the "days" setting, we can only remove one
|
43
|
-
|
44
|
-
retention = PipelineProviderRetention(days=1, minimum=3, maximum=None)
|
45
|
-
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 3
|
46
|
-
# We would have removed four from the "days" setting, we can only remove three
|
47
|
-
|
48
|
-
retention = PipelineProviderRetention(days=1, minimum=1, maximum=None)
|
49
|
-
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 4
|
50
|
-
# Removing 4 we still have two, we're fine.
|
51
|
-
|
52
|
-
|
53
|
-
# Maximum set, it takes precedence over "days"
|
54
|
-
def test_days_and_maximum(now: datetime, pipeline_runs: list[dict[str, Any]]) -> None:
|
55
|
-
retention = PipelineProviderRetention(days=1, minimum=None, maximum=1)
|
56
|
-
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 5
|
57
|
-
# we have a max of 1, no matter what "days" says.
|
58
|
-
|
59
|
-
retention = PipelineProviderRetention(days=1, minimum=None, maximum=3)
|
60
|
-
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 4
|
61
|
-
# by removing 4 we comply with the max setting of three.
|
62
|
-
|
63
|
-
retention = PipelineProviderRetention(days=2, minimum=None, maximum=3)
|
64
|
-
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 3
|
65
|
-
# We would have remove only two following "days", but max tells us otherwise.
|
@@ -1,282 +0,0 @@
|
|
1
|
-
from collections.abc import Callable, Mapping
|
2
|
-
from typing import Any
|
3
|
-
from unittest.mock import call
|
4
|
-
|
5
|
-
import pytest
|
6
|
-
from pytest_mock import MockerFixture
|
7
|
-
|
8
|
-
from reconcile.gql_definitions.openshift_serviceaccount_tokens.tokens import NamespaceV1
|
9
|
-
from reconcile.openshift_serviceaccount_tokens import (
|
10
|
-
QONTRACT_INTEGRATION,
|
11
|
-
canonicalize_namespaces,
|
12
|
-
construct_sa_token_oc_resource,
|
13
|
-
fetch_desired_state,
|
14
|
-
get_namespaces_with_serviceaccount_tokens,
|
15
|
-
get_tokens_for_service_account,
|
16
|
-
service_account_token_request,
|
17
|
-
write_outputs_to_vault,
|
18
|
-
)
|
19
|
-
from reconcile.test.fixtures import Fixtures
|
20
|
-
from reconcile.utils.oc import OC_Map, OCCli
|
21
|
-
from reconcile.utils.openshift_resource import ResourceInventory
|
22
|
-
from reconcile.utils.vault import _VaultClient
|
23
|
-
|
24
|
-
|
25
|
-
@pytest.fixture
|
26
|
-
def fx() -> Fixtures:
|
27
|
-
return Fixtures("openshift_serviceaccount_tokens")
|
28
|
-
|
29
|
-
|
30
|
-
@pytest.fixture
|
31
|
-
def query_func(
|
32
|
-
data_factory: Callable[[type[NamespaceV1], Mapping[str, Any]], Mapping[str, Any]],
|
33
|
-
fx: Fixtures,
|
34
|
-
) -> Callable:
|
35
|
-
def q(*args: Any, **kwargs: Any) -> dict:
|
36
|
-
return {
|
37
|
-
"namespaces": [
|
38
|
-
data_factory(NamespaceV1, item)
|
39
|
-
for item in fx.get_anymarkup("namespaces.yml")["namespaces"]
|
40
|
-
]
|
41
|
-
}
|
42
|
-
|
43
|
-
return q
|
44
|
-
|
45
|
-
|
46
|
-
@pytest.fixture
|
47
|
-
def namespaces(query_func: Callable) -> list[NamespaceV1]:
|
48
|
-
return get_namespaces_with_serviceaccount_tokens(query_func)
|
49
|
-
|
50
|
-
|
51
|
-
@pytest.fixture
|
52
|
-
def ri(namespaces: list[NamespaceV1]) -> ResourceInventory:
|
53
|
-
_ri = ResourceInventory()
|
54
|
-
_ri.initialize_resource_type(
|
55
|
-
cluster="cluster",
|
56
|
-
namespace="namespace",
|
57
|
-
resource_type="Secret",
|
58
|
-
)
|
59
|
-
_ri.initialize_resource_type(
|
60
|
-
cluster="another-cluster",
|
61
|
-
namespace="platform-changelog-stage",
|
62
|
-
resource_type="Secret",
|
63
|
-
)
|
64
|
-
_ri.initialize_resource_type(
|
65
|
-
cluster="another-cluster",
|
66
|
-
namespace="with-openshift-serviceaccount-tokens",
|
67
|
-
resource_type="Secret",
|
68
|
-
)
|
69
|
-
for ns in namespaces:
|
70
|
-
_ri.initialize_resource_type(
|
71
|
-
cluster=ns.cluster.name, namespace=ns.name, resource_type="Secret"
|
72
|
-
)
|
73
|
-
return _ri
|
74
|
-
|
75
|
-
|
76
|
-
def test_openshift_serviceaccount_tokens__construct_sa_token_oc_resource() -> None:
|
77
|
-
qr = construct_sa_token_oc_resource("foobar", "token")
|
78
|
-
assert qr.body == {
|
79
|
-
"apiVersion": "v1",
|
80
|
-
"data": {"token": "token"},
|
81
|
-
"kind": "Secret",
|
82
|
-
"metadata": {"name": "foobar"},
|
83
|
-
"type": "Opaque",
|
84
|
-
}
|
85
|
-
|
86
|
-
|
87
|
-
def test_openshift_serviceaccount_tokens__get_tokens_for_service_account() -> None:
|
88
|
-
foobar_secret = {
|
89
|
-
"metadata": {
|
90
|
-
"annotations": {"kubernetes.io/service-account.name": "foobar-account"}
|
91
|
-
},
|
92
|
-
"type": "kubernetes.io/service-account-token",
|
93
|
-
}
|
94
|
-
assert get_tokens_for_service_account(
|
95
|
-
service_account="foobar-account",
|
96
|
-
tokens=[
|
97
|
-
foobar_secret,
|
98
|
-
{
|
99
|
-
"metadata": {
|
100
|
-
"annotations": {
|
101
|
-
"kubernetes.io/service-account.name": "just-another-account"
|
102
|
-
}
|
103
|
-
},
|
104
|
-
"type": "kubernetes.io/service-account-token",
|
105
|
-
},
|
106
|
-
foobar_secret,
|
107
|
-
{
|
108
|
-
"metadata": {"annotations": {"whatever": "foobar-account"}},
|
109
|
-
"type": "not-a-service-account-token",
|
110
|
-
},
|
111
|
-
],
|
112
|
-
) == [foobar_secret, foobar_secret]
|
113
|
-
|
114
|
-
|
115
|
-
def test_openshift_serviceaccount_tokens__write_outputs_to_vault(
|
116
|
-
mocker: MockerFixture, ri: ResourceInventory
|
117
|
-
) -> None:
|
118
|
-
vault_client = mocker.create_autospec(_VaultClient)
|
119
|
-
|
120
|
-
ri.add_desired(
|
121
|
-
cluster="cluster",
|
122
|
-
namespace="namespace",
|
123
|
-
resource_type="Secret",
|
124
|
-
name="name",
|
125
|
-
value=construct_sa_token_oc_resource("name", "token"),
|
126
|
-
)
|
127
|
-
write_outputs_to_vault(vault_client, "path/to/secrets", ri)
|
128
|
-
assert vault_client.write.call_count == 2
|
129
|
-
vault_client.write.assert_has_calls([
|
130
|
-
call({
|
131
|
-
"path": "path/to/secrets/openshift-serviceaccount-tokens/cluster/namespace/name",
|
132
|
-
"data": {"token": "token"},
|
133
|
-
}),
|
134
|
-
call({
|
135
|
-
"path": "path/to/secrets/openshift-serviceaccount-tokens/shared-resources/name",
|
136
|
-
"data": {"token": "token"},
|
137
|
-
}),
|
138
|
-
])
|
139
|
-
|
140
|
-
|
141
|
-
def test_openshift_serviceaccount_tokens__get_namespaces_with_serviceaccount_tokens(
|
142
|
-
namespaces: list[NamespaceV1],
|
143
|
-
) -> None:
|
144
|
-
assert len(namespaces) == 3
|
145
|
-
assert namespaces[0].name == "with-openshift-serviceaccount-tokens"
|
146
|
-
assert namespaces[1].name == "with-shared-resources"
|
147
|
-
assert (
|
148
|
-
namespaces[2].name
|
149
|
-
== "with-openshift-serviceaccount-tokens-and-shared-resources"
|
150
|
-
)
|
151
|
-
|
152
|
-
|
153
|
-
def test_openshift_serviceaccount_tokens__canonicalize_namespaces(
|
154
|
-
namespaces: list[NamespaceV1],
|
155
|
-
) -> None:
|
156
|
-
nss = canonicalize_namespaces(namespaces)
|
157
|
-
# sort by number of tokens and namespace name
|
158
|
-
nss.sort(key=lambda n: f"{len(n.openshift_service_account_tokens or [])}-{n.name}")
|
159
|
-
assert len(nss) == 6
|
160
|
-
|
161
|
-
# added via remote service account token
|
162
|
-
assert nss[0].name == "observability"
|
163
|
-
assert nss[0].openshift_service_account_tokens is None
|
164
|
-
assert nss[1].name == "platform-changelog-stage"
|
165
|
-
assert nss[1].openshift_service_account_tokens is None
|
166
|
-
assert nss[2].name == "with-openshift-serviceaccount-tokens"
|
167
|
-
assert nss[2].openshift_service_account_tokens is None
|
168
|
-
|
169
|
-
# namespace with tokens or shared resources defined
|
170
|
-
assert nss[3].name == "with-shared-resources"
|
171
|
-
assert nss[3].cluster.name == "cluster"
|
172
|
-
assert len(nss[3].openshift_service_account_tokens or []) == 1
|
173
|
-
|
174
|
-
assert nss[4].name == "with-openshift-serviceaccount-tokens"
|
175
|
-
assert len(nss[4].openshift_service_account_tokens or []) == 2
|
176
|
-
|
177
|
-
assert nss[5].name == "with-openshift-serviceaccount-tokens-and-shared-resources"
|
178
|
-
assert len(nss[5].openshift_service_account_tokens or []) == 2
|
179
|
-
|
180
|
-
|
181
|
-
def test_openshift_serviceaccount_tokens__fetch_desired_state(
|
182
|
-
mocker: MockerFixture, namespaces: list[NamespaceV1], ri: ResourceInventory
|
183
|
-
) -> None:
|
184
|
-
grafana_secret = {
|
185
|
-
"metadata": {
|
186
|
-
"name": "grafana-secret",
|
187
|
-
"annotations": {"kubernetes.io/service-account.name": "grafana"},
|
188
|
-
},
|
189
|
-
"type": "kubernetes.io/service-account-token",
|
190
|
-
"data": {"token": "super-secret-token"},
|
191
|
-
}
|
192
|
-
|
193
|
-
oc_map = mocker.create_autospec(OC_Map)
|
194
|
-
oc = mocker.create_autospec(OCCli)
|
195
|
-
oc_map.get.return_value = oc
|
196
|
-
oc.get_items.return_value = [
|
197
|
-
grafana_secret,
|
198
|
-
{
|
199
|
-
"metadata": {
|
200
|
-
"name": "just-another-account-secret",
|
201
|
-
"annotations": {
|
202
|
-
"kubernetes.io/service-account.name": "just-another-account"
|
203
|
-
},
|
204
|
-
},
|
205
|
-
"type": "kubernetes.io/service-account-token",
|
206
|
-
},
|
207
|
-
grafana_secret,
|
208
|
-
{
|
209
|
-
"metadata": {
|
210
|
-
"name": "just-something-different",
|
211
|
-
"annotations": {"whatever": "grafana"},
|
212
|
-
},
|
213
|
-
"type": "not-a-service-account-token",
|
214
|
-
},
|
215
|
-
]
|
216
|
-
fetch_desired_state(
|
217
|
-
namespaces=namespaces,
|
218
|
-
ri=ri,
|
219
|
-
oc_map=oc_map,
|
220
|
-
)
|
221
|
-
assert (
|
222
|
-
len(
|
223
|
-
ri._clusters["cluster"]["with-openshift-serviceaccount-tokens"]["Secret"][
|
224
|
-
"desired"
|
225
|
-
].keys()
|
226
|
-
)
|
227
|
-
== 2
|
228
|
-
)
|
229
|
-
assert (
|
230
|
-
len(
|
231
|
-
ri._clusters["cluster"][
|
232
|
-
"with-openshift-serviceaccount-tokens-and-shared-resources"
|
233
|
-
]["Secret"]["desired"].keys()
|
234
|
-
)
|
235
|
-
== 1
|
236
|
-
)
|
237
|
-
assert (
|
238
|
-
"another-cluster-with-openshift-serviceaccount-tokens-grafana"
|
239
|
-
in ri._clusters["cluster"]["with-openshift-serviceaccount-tokens"]["Secret"][
|
240
|
-
"desired"
|
241
|
-
]
|
242
|
-
)
|
243
|
-
|
244
|
-
|
245
|
-
def test_openshift_serviceaccount_tokens__fetch_desired_state_create_token(
|
246
|
-
mocker: MockerFixture, namespaces: list[NamespaceV1], ri: ResourceInventory
|
247
|
-
) -> None:
|
248
|
-
oc_map = mocker.create_autospec(OC_Map)
|
249
|
-
oc = mocker.create_autospec(OCCli)
|
250
|
-
oc_map.get.return_value = oc
|
251
|
-
oc.get_items.return_value = []
|
252
|
-
|
253
|
-
fetch_desired_state(
|
254
|
-
namespaces=[namespaces[0]],
|
255
|
-
ri=ri,
|
256
|
-
oc_map=oc_map,
|
257
|
-
)
|
258
|
-
|
259
|
-
assert (
|
260
|
-
len(
|
261
|
-
ri._clusters["cluster"]["with-openshift-serviceaccount-tokens"]["Secret"][
|
262
|
-
"desired"
|
263
|
-
].keys()
|
264
|
-
)
|
265
|
-
== 1
|
266
|
-
)
|
267
|
-
r = next(
|
268
|
-
iter(
|
269
|
-
ri._clusters["cluster"]["with-openshift-serviceaccount-tokens"]["Secret"][
|
270
|
-
"desired"
|
271
|
-
].values()
|
272
|
-
)
|
273
|
-
)
|
274
|
-
assert r.body["type"] == "kubernetes.io/service-account-token"
|
275
|
-
|
276
|
-
|
277
|
-
def test_openshift_serviceaccount_tokens__service_account_token_request() -> None:
|
278
|
-
resource = service_account_token_request("grafana")
|
279
|
-
assert resource.name.startswith("grafana-")
|
280
|
-
assert resource.body["type"] == "kubernetes.io/service-account-token"
|
281
|
-
assert resource.kind == "Secret"
|
282
|
-
assert resource.integration != QONTRACT_INTEGRATION
|