qontract-reconcile 0.10.2.dev14__py3-none-any.whl → 0.10.2.dev15__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.dev14.dist-info → qontract_reconcile-0.10.2.dev15.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.2.dev14.dist-info → qontract_reconcile-0.10.2.dev15.dist-info}/RECORD +133 -133
- reconcile/acs_rbac.py +2 -4
- reconcile/aus/base.py +13 -13
- reconcile/aws_ami_share.py +1 -2
- reconcile/aws_cloudwatch_log_retention/integration.py +1 -1
- reconcile/aws_saml_idp/integration.py +1 -1
- reconcile/aws_saml_roles/integration.py +1 -1
- reconcile/aws_version_sync/integration.py +3 -3
- reconcile/change_owners/change_owners.py +8 -5
- reconcile/change_owners/change_types.py +18 -18
- reconcile/change_owners/changes.py +8 -9
- reconcile/change_owners/decision.py +12 -15
- reconcile/change_owners/self_service_roles.py +6 -4
- reconcile/change_owners/tester.py +8 -10
- reconcile/cli.py +9 -11
- reconcile/closedbox_endpoint_monitoring_base.py +1 -1
- reconcile/cna/integration.py +2 -2
- reconcile/dashdotdb_base.py +2 -2
- reconcile/dashdotdb_cso.py +1 -1
- reconcile/dashdotdb_dora.py +6 -4
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +15 -19
- reconcile/email_sender.py +4 -8
- reconcile/external_resources/secrets_sync.py +2 -2
- reconcile/external_resources/state.py +17 -17
- reconcile/gabi_authorized_users.py +3 -3
- reconcile/gcr_mirror.py +2 -2
- reconcile/github_org.py +9 -13
- reconcile/gitlab_housekeeping.py +1 -1
- reconcile/gitlab_owners.py +10 -12
- reconcile/gitlab_permissions.py +5 -4
- reconcile/glitchtip/integration.py +14 -14
- reconcile/glitchtip_project_alerts/integration.py +3 -4
- reconcile/integrations_manager.py +1 -2
- reconcile/jenkins_job_builds_cleaner.py +7 -5
- reconcile/jenkins_roles.py +10 -6
- reconcile/jenkins_worker_fleets.py +5 -4
- reconcile/jira_permissions_validator.py +2 -6
- reconcile/ldap_groups/integration.py +3 -2
- reconcile/ocm_groups.py +5 -5
- reconcile/ocm_update_recommended_version.py +2 -2
- reconcile/openshift_base.py +15 -20
- reconcile/openshift_groups.py +9 -8
- reconcile/openshift_namespace_labels.py +3 -4
- reconcile/openshift_namespaces.py +1 -1
- reconcile/openshift_network_policies.py +1 -1
- reconcile/openshift_resources_base.py +4 -4
- reconcile/openshift_serviceaccount_tokens.py +1 -1
- reconcile/openshift_tekton_resources.py +1 -2
- reconcile/openshift_users.py +5 -4
- reconcile/prometheus_rules_tester/integration.py +8 -8
- reconcile/quay_mirror.py +3 -4
- reconcile/quay_mirror_org.py +1 -1
- reconcile/rhidp/ocm_oidc_idp/base.py +10 -15
- reconcile/run_integration.py +7 -7
- reconcile/saas_auto_promotions_manager/publisher.py +1 -1
- reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +3 -9
- reconcile/service_dependencies.py +2 -7
- reconcile/skupper_network/reconciler.py +5 -5
- reconcile/skupper_network/site_controller.py +3 -3
- reconcile/sql_query.py +5 -5
- reconcile/status_board.py +24 -24
- reconcile/terraform_cloudflare_users.py +2 -2
- reconcile/terraform_repo.py +6 -6
- reconcile/terraform_users.py +8 -5
- reconcile/terraform_vpc_peerings.py +1 -1
- reconcile/terraform_vpc_resources/integration.py +1 -1
- reconcile/typed_queries/app_interface_deadmanssnitch_settings.py +1 -1
- reconcile/typed_queries/app_quay_repos_escalation_policies.py +1 -1
- reconcile/typed_queries/aws_vpc_requests.py +1 -1
- reconcile/typed_queries/aws_vpcs.py +1 -1
- reconcile/typed_queries/clusters.py +1 -1
- reconcile/typed_queries/clusters_minimal.py +1 -1
- reconcile/typed_queries/clusters_with_dms.py +1 -1
- reconcile/typed_queries/dynatrace_environments.py +1 -1
- reconcile/typed_queries/dynatrace_token_provider_token_specs.py +1 -1
- reconcile/typed_queries/reserved_networks.py +1 -1
- reconcile/typed_queries/saas_files.py +1 -1
- reconcile/typed_queries/slo_documents.py +1 -1
- reconcile/typed_queries/status_board.py +1 -2
- reconcile/utils/amtool.py +2 -2
- reconcile/utils/aws_api.py +10 -10
- reconcile/utils/aws_helper.py +1 -1
- reconcile/utils/binary.py +1 -2
- reconcile/utils/differ.py +4 -7
- reconcile/utils/dnsutils.py +4 -12
- reconcile/utils/external_resources.py +1 -2
- reconcile/utils/gitlab_api.py +2 -4
- reconcile/utils/glitchtip/models.py +1 -1
- reconcile/utils/helm.py +1 -1
- reconcile/utils/instrumented_wrappers.py +2 -2
- reconcile/utils/jjb_client.py +1 -1
- reconcile/utils/jump_host.py +1 -1
- reconcile/utils/metrics.py +6 -11
- reconcile/utils/mr/aws_access.py +1 -1
- reconcile/utils/mr/base.py +2 -4
- reconcile/utils/mr/notificator.py +1 -1
- reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py +1 -1
- reconcile/utils/oc.py +17 -31
- reconcile/utils/oc_map.py +1 -1
- reconcile/utils/ocm/base.py +4 -2
- reconcile/utils/ocm/search_filters.py +4 -3
- reconcile/utils/ocm/status_board.py +2 -2
- reconcile/utils/ocm/upgrades.py +4 -7
- reconcile/utils/ocm_base_client.py +1 -1
- reconcile/utils/openshift_resource.py +1 -1
- reconcile/utils/promtool.py +1 -1
- reconcile/utils/quay_api.py +1 -3
- reconcile/utils/raw_github_api.py +3 -10
- reconcile/utils/repo_owners.py +5 -5
- reconcile/utils/rest_api_base.py +1 -2
- reconcile/utils/rosa/rosa_cli.py +3 -3
- reconcile/utils/saasherder/saasherder.py +9 -15
- reconcile/utils/secret_reader.py +2 -2
- reconcile/utils/sharding.py +2 -2
- reconcile/utils/state.py +5 -5
- reconcile/utils/terraform_client.py +2 -2
- reconcile/utils/terrascript/cloudflare_resources.py +4 -6
- reconcile/utils/terrascript_aws_client.py +16 -28
- reconcile/utils/vault.py +2 -2
- reconcile/utils/vcs.py +8 -16
- reconcile/vault_replication.py +1 -8
- tools/app_interface_reporter.py +1 -1
- tools/cli_commands/container_images_report.py +1 -1
- tools/cli_commands/cost_report/view.py +4 -2
- tools/cli_commands/gpg_encrypt.py +1 -5
- tools/qontract_cli.py +14 -13
- tools/saas_metrics_exporter/commit_distance/channel.py +1 -1
- tools/saas_promotion_state/saas_promotion_state.py +1 -1
- tools/sd_app_sre_alert_report.py +3 -3
- {qontract_reconcile-0.10.2.dev14.dist-info → qontract_reconcile-0.10.2.dev15.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev14.dist-info → qontract_reconcile-0.10.2.dev15.dist-info}/entry_points.txt +0 -0
@@ -44,28 +44,21 @@ class RawGithubApi:
|
|
44
44
|
result = res.json()
|
45
45
|
|
46
46
|
if isinstance(result, list):
|
47
|
-
elements =
|
48
|
-
|
49
|
-
for element in result:
|
50
|
-
elements.append(element)
|
51
|
-
|
47
|
+
elements = list(result)
|
52
48
|
while "last" in res.links and "next" in res.links:
|
53
49
|
if res.links["last"]["url"] == res.links["next"]["url"]:
|
54
50
|
req_url = res.links["next"]["url"]
|
55
51
|
res = requests.get(req_url, headers=h, timeout=60)
|
56
52
|
res.raise_for_status()
|
57
53
|
|
58
|
-
for element in res.json()
|
59
|
-
elements.append(element)
|
60
|
-
|
54
|
+
elements.extend(element for element in res.json())
|
61
55
|
return elements
|
62
56
|
|
63
57
|
req_url = res.links["next"]["url"]
|
64
58
|
res = requests.get(req_url, headers=h, timeout=60)
|
65
59
|
res.raise_for_status()
|
66
60
|
|
67
|
-
for element in res.json()
|
68
|
-
elements.append(element)
|
61
|
+
elements.extend(element for element in res.json())
|
69
62
|
|
70
63
|
return elements
|
71
64
|
|
reconcile/utils/repo_owners.py
CHANGED
@@ -92,15 +92,15 @@ class RepoOwners:
|
|
92
92
|
:return: the path closest owners
|
93
93
|
:rtype: dict
|
94
94
|
"""
|
95
|
-
candidates = [
|
95
|
+
candidates = [
|
96
|
+
owned_path
|
97
|
+
for owned_path in self.owners_map
|
98
|
+
if os.path.commonpath([path, owned_path]) == owned_path
|
99
|
+
]
|
96
100
|
|
97
101
|
if "." in self.owners_map:
|
98
102
|
candidates.append(".")
|
99
103
|
|
100
|
-
for owned_path in self.owners_map:
|
101
|
-
if os.path.commonpath([path, owned_path]) == owned_path:
|
102
|
-
candidates.append(owned_path)
|
103
|
-
|
104
104
|
if candidates:
|
105
105
|
# The longest owned_path is the chosen
|
106
106
|
elected = max(candidates, key=len)
|
reconcile/utils/rest_api_base.py
CHANGED
@@ -81,8 +81,7 @@ class ApiBase:
|
|
81
81
|
return response.json()
|
82
82
|
except requests.exceptions.JSONDecodeError:
|
83
83
|
logging.error(
|
84
|
-
f"Failed to decode JSON response from {url}"
|
85
|
-
f"Response: {response.text}"
|
84
|
+
f"Failed to decode JSON response from {url}Response: {response.text}"
|
86
85
|
)
|
87
86
|
raise
|
88
87
|
|
reconcile/utils/rosa/rosa_cli.py
CHANGED
@@ -141,13 +141,13 @@ class RosaJob(K8sJob, BaseModel, frozen=True, arbitrary_types_allowed=True):
|
|
141
141
|
}
|
142
142
|
|
143
143
|
def annotations(self) -> dict[str, str]:
|
144
|
-
|
144
|
+
annotations = {
|
145
145
|
"qontract.rosa.aws_account_id": self.aws_account_id,
|
146
146
|
"qontract.rosa.aws_region": self.aws_region,
|
147
147
|
"qontract.rosa.ocm_org_id": self.ocm_org_id,
|
148
148
|
}
|
149
|
-
|
150
|
-
return
|
149
|
+
annotations.update(self.extra_annotations)
|
150
|
+
return annotations
|
151
151
|
|
152
152
|
def secret_data(self) -> dict[str, str]:
|
153
153
|
return {"OCM_TOKEN": self.ocm_token}
|
@@ -226,7 +226,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
226
226
|
if not allowed_secret_parameter_paths:
|
227
227
|
self.valid = False
|
228
228
|
logging.error(
|
229
|
-
f"[{saas_file_name}]
|
229
|
+
f"[{saas_file_name}] missing allowedSecretParameterPaths section"
|
230
230
|
)
|
231
231
|
return
|
232
232
|
for sp in secret_parameters:
|
@@ -558,8 +558,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
558
558
|
) -> None:
|
559
559
|
if target.image and target.upstream:
|
560
560
|
logging.error(
|
561
|
-
f"[{saas_file_name}/{resource_template_name}] "
|
562
|
-
f"image used with upstream"
|
561
|
+
f"[{saas_file_name}/{resource_template_name}] image used with upstream"
|
563
562
|
)
|
564
563
|
self.valid = False
|
565
564
|
|
@@ -1056,35 +1055,30 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
1056
1055
|
|
1057
1056
|
@staticmethod
|
1058
1057
|
def _collect_images(resource: Resource) -> set[str]:
|
1059
|
-
images = set()
|
1058
|
+
images: set[str] = set()
|
1060
1059
|
# resources with pod templates
|
1061
1060
|
with suppress(KeyError):
|
1062
1061
|
template = resource["spec"]["template"]
|
1063
|
-
for c in template["spec"]["containers"]
|
1064
|
-
images.add(c["image"])
|
1062
|
+
images.update(c["image"] for c in template["spec"]["containers"])
|
1065
1063
|
# init containers
|
1066
1064
|
with suppress(KeyError):
|
1067
1065
|
template = resource["spec"]["template"]
|
1068
|
-
for c in template["spec"]["initContainers"]
|
1069
|
-
images.add(c["image"])
|
1066
|
+
images.update(c["image"] for c in template["spec"]["initContainers"])
|
1070
1067
|
# CronJob
|
1071
1068
|
with suppress(KeyError):
|
1072
1069
|
template = resource["spec"]["jobTemplate"]["spec"]["template"]
|
1073
|
-
for c in template["spec"]["containers"]
|
1074
|
-
images.add(c["image"])
|
1070
|
+
images.update(c["image"] for c in template["spec"]["containers"])
|
1075
1071
|
# CatalogSource templates
|
1076
1072
|
with suppress(KeyError):
|
1077
1073
|
images.add(resource["spec"]["image"])
|
1078
1074
|
# ClowdApp deployments
|
1079
1075
|
with suppress(KeyError):
|
1080
1076
|
deployments = resource["spec"]["deployments"]
|
1081
|
-
for d in deployments
|
1082
|
-
images.add(d["podSpec"]["image"])
|
1077
|
+
images.update(d["podSpec"]["image"] for d in deployments)
|
1083
1078
|
# ClowdApp jobs
|
1084
1079
|
with suppress(KeyError, TypeError):
|
1085
1080
|
jobs = resource["spec"]["jobs"]
|
1086
|
-
for j in jobs
|
1087
|
-
images.add(j["podSpec"]["image"])
|
1081
|
+
images.update(j["podSpec"]["image"] for j in jobs)
|
1088
1082
|
|
1089
1083
|
return images
|
1090
1084
|
|
@@ -1872,7 +1866,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
1872
1866
|
# not have promotion_data yet
|
1873
1867
|
if not config_hashes or not promotion.promotion_data:
|
1874
1868
|
logging.info(
|
1875
|
-
"Promotion data is missing; rely on the success
|
1869
|
+
"Promotion data is missing; rely on the success state only"
|
1876
1870
|
)
|
1877
1871
|
continue
|
1878
1872
|
|
reconcile/utils/secret_reader.py
CHANGED
@@ -163,7 +163,7 @@ class VaultSecretReader(SecretReaderBase):
|
|
163
163
|
)
|
164
164
|
except Forbidden:
|
165
165
|
raise VaultForbidden(
|
166
|
-
f"permission denied reading vault secret
|
166
|
+
f"permission denied reading vault secret at {path}"
|
167
167
|
) from None
|
168
168
|
except vault.SecretNotFound as e:
|
169
169
|
raise SecretNotFound(*e.args) from e
|
@@ -315,7 +315,7 @@ class SecretReader(SecretReaderBase):
|
|
315
315
|
data = self.vault_client.read_all(params) # type: ignore[attr-defined] # mypy doesn't recognize the VaultClient.__new__ method
|
316
316
|
except Forbidden:
|
317
317
|
raise VaultForbidden(
|
318
|
-
f"permission denied reading vault secret
|
318
|
+
f"permission denied reading vault secret at {path}"
|
319
319
|
) from None
|
320
320
|
except vault.SecretNotFound as e:
|
321
321
|
raise SecretNotFound(*e.args) from e
|
reconcile/utils/sharding.py
CHANGED
@@ -4,8 +4,8 @@ import os
|
|
4
4
|
|
5
5
|
LOG = logging.getLogger(__name__)
|
6
6
|
|
7
|
-
SHARDS = int(os.environ.get("SHARDS", 1))
|
8
|
-
SHARD_ID = int(os.environ.get("SHARD_ID", 0))
|
7
|
+
SHARDS = int(os.environ.get("SHARDS", "1"))
|
8
|
+
SHARD_ID = int(os.environ.get("SHARD_ID", "0"))
|
9
9
|
|
10
10
|
|
11
11
|
def is_in_shard(value):
|
reconcile/utils/state.py
CHANGED
@@ -346,7 +346,7 @@ class State:
|
|
346
346
|
:type key: string
|
347
347
|
"""
|
348
348
|
if not force and self.exists(key):
|
349
|
-
raise KeyError(f"[state] key {key} already
|
349
|
+
raise KeyError(f"[state] key {key} already exists in {self.state_path}")
|
350
350
|
self._set(key, value, metadata=metadata)
|
351
351
|
|
352
352
|
def _set(
|
@@ -430,16 +430,16 @@ class State:
|
|
430
430
|
This method is not thread-safe nor multi-process-safe! There is no locking mechanism in place.
|
431
431
|
"""
|
432
432
|
try:
|
433
|
-
|
433
|
+
current_value = self[key]
|
434
434
|
except KeyError:
|
435
|
-
|
436
|
-
state_obj = TransactionStateObj(key, value=
|
435
|
+
current_value = None
|
436
|
+
state_obj = TransactionStateObj(key, value=current_value)
|
437
437
|
try:
|
438
438
|
yield state_obj
|
439
439
|
except AbortStateTransaction:
|
440
440
|
return
|
441
441
|
else:
|
442
|
-
if state_obj.changed and state_obj.value !=
|
442
|
+
if state_obj.changed and state_obj.value != current_value:
|
443
443
|
self[state_obj.key] = state_obj.value
|
444
444
|
elif value is not None and state_obj.value != value:
|
445
445
|
self[state_obj.key] = value
|
@@ -477,7 +477,7 @@ class TerraformClient: # pylint: disable=too-many-public-methods
|
|
477
477
|
tf_resource = spec.resource
|
478
478
|
replica_src = tf_resource.get("replica_source")
|
479
479
|
if replica_src:
|
480
|
-
replica_source_name = f
|
480
|
+
replica_source_name = f"{replica_src}-{tf_resource.get('provider')}"
|
481
481
|
# Creating a dict that is convenient to use inside the
|
482
482
|
# loop processing the formatted_output
|
483
483
|
replicas_info[spec.provisioner_name][spec.output_prefix] = (
|
@@ -659,7 +659,7 @@ class TerraformClient: # pylint: disable=too-many-public-methods
|
|
659
659
|
def cleanup(self):
|
660
660
|
if self._aws_api is not None:
|
661
661
|
self._aws_api.cleanup()
|
662
|
-
for
|
662
|
+
for wd in self.working_dirs.values():
|
663
663
|
shutil.rmtree(wd)
|
664
664
|
|
665
665
|
def _can_skip_rds_modifications(
|
@@ -376,18 +376,16 @@ class CloudflareLogpushOwnershipChallengeResource(TerrascriptResource):
|
|
376
376
|
destination_conf = values.get("destination_conf")
|
377
377
|
zone = values.get("zone_name")
|
378
378
|
if zone:
|
379
|
-
resources
|
379
|
+
resources += [
|
380
380
|
self.cloudflare_zone(
|
381
381
|
safe_resource_id(zone), name=zone, account_id="${var.account_id}"
|
382
|
-
)
|
383
|
-
)
|
384
|
-
resources.append(
|
382
|
+
),
|
385
383
|
cloudflare_logpush_ownership_challenge(
|
386
384
|
self._spec.identifier,
|
387
385
|
zone_id=f"${{data.cloudflare_zone.{safe_resource_id(zone)}.id}}",
|
388
386
|
destination_conf=destination_conf,
|
389
|
-
)
|
390
|
-
|
387
|
+
),
|
388
|
+
]
|
391
389
|
else:
|
392
390
|
resources.append(
|
393
391
|
cloudflare_logpush_ownership_challenge(
|
@@ -2670,8 +2670,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
2670
2670
|
tf_resources.append(Output(output_name, value=switch_role_arn))
|
2671
2671
|
else:
|
2672
2672
|
raise KeyError(
|
2673
|
-
f"[{account}/{identifier}] "
|
2674
|
-
"expected one of ocm_map or assume_role"
|
2673
|
+
f"[{account}/{identifier}] expected one of ocm_map or assume_role"
|
2675
2674
|
)
|
2676
2675
|
|
2677
2676
|
self.add_resources(account, tf_resources)
|
@@ -4565,14 +4564,14 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
4565
4564
|
|
4566
4565
|
# add arn to output
|
4567
4566
|
output_name = (
|
4568
|
-
f"{output_prefix}__cloudwatch_log_group_
|
4567
|
+
f"{output_prefix}__cloudwatch_log_group_{log_type.lower()}_arn"
|
4569
4568
|
)
|
4570
4569
|
output_value = arn
|
4571
4570
|
tf_resources.append(Output(output_name, value=output_value))
|
4572
4571
|
|
4573
4572
|
# add name to output
|
4574
4573
|
output_name = (
|
4575
|
-
f"{output_prefix}__cloudwatch_log_group_
|
4574
|
+
f"{output_prefix}__cloudwatch_log_group_{log_type.lower()}_name"
|
4576
4575
|
)
|
4577
4576
|
output_value = log_type_identifier
|
4578
4577
|
tf_resources.append(Output(output_name, value=output_value))
|
@@ -5078,7 +5077,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
5078
5077
|
secret = common_values.get("secret", None)
|
5079
5078
|
if secret is None:
|
5080
5079
|
raise KeyError(
|
5081
|
-
"no secret defined for s3_cloudfront_public_key
|
5080
|
+
f"no secret defined for s3_cloudfront_public_key {identifier}"
|
5082
5081
|
)
|
5083
5082
|
|
5084
5083
|
secret_data = self.secret_reader.read_all(secret)
|
@@ -5429,8 +5428,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
5429
5428
|
weight_sum += a["weight"]
|
5430
5429
|
if weight_sum != 100:
|
5431
5430
|
raise ValueError(
|
5432
|
-
"sum of weights for a rule should be 100"
|
5433
|
-
f" given: {weight_sum}"
|
5431
|
+
f"sum of weights for a rule should be 100 given: {weight_sum}"
|
5434
5432
|
)
|
5435
5433
|
elif action_type == "fixed-response":
|
5436
5434
|
fr_data = action.get("fixed_response", {})
|
@@ -5604,8 +5602,8 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
5604
5602
|
if extra_tags:
|
5605
5603
|
tags.update(json.loads(extra_tags))
|
5606
5604
|
# common_values is untyped, so casting is necessary
|
5607
|
-
region = cast(
|
5608
|
-
str, self.default_regions.get(account)
|
5605
|
+
region = cast(
|
5606
|
+
str, common_values.get("region") or self.default_regions.get(account)
|
5609
5607
|
)
|
5610
5608
|
|
5611
5609
|
template_values = {
|
@@ -6313,7 +6311,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
6313
6311
|
http_method="${aws_api_gateway_method.gw_method_proxy_any.http_method}",
|
6314
6312
|
integration_http_method="${aws_api_gateway_method.gw_method_proxy_any.http_method}",
|
6315
6313
|
connection_id=f"${{{api_gateway_vpc_link_resource.id}}}",
|
6316
|
-
uri=f
|
6314
|
+
uri=f"{common_values.get('api_proxy_uri')}/api/{{proxy}}",
|
6317
6315
|
**integration_proxy_args,
|
6318
6316
|
)
|
6319
6317
|
tf_resources.append(api_gateway_integration_proxy_resource)
|
@@ -6829,42 +6827,32 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
6829
6827
|
tf_resources.append(scram_secret_association)
|
6830
6828
|
|
6831
6829
|
# outputs
|
6832
|
-
tf_resources
|
6830
|
+
tf_resources += [
|
6833
6831
|
Output(
|
6834
6832
|
output_prefix + "__zookeeper_connect_string",
|
6835
6833
|
value="${" + msk_cluster.zookeeper_connect_string + "}",
|
6836
|
-
)
|
6837
|
-
)
|
6838
|
-
tf_resources.append(
|
6834
|
+
),
|
6839
6835
|
Output(
|
6840
6836
|
output_prefix + "__zookeeper_connect_string_tls",
|
6841
6837
|
value="${" + msk_cluster.zookeeper_connect_string_tls + "}",
|
6842
|
-
)
|
6843
|
-
)
|
6844
|
-
tf_resources.append(
|
6838
|
+
),
|
6845
6839
|
Output(
|
6846
6840
|
output_prefix + "__bootstrap_brokers",
|
6847
6841
|
value="${" + msk_cluster.bootstrap_brokers + "}",
|
6848
|
-
)
|
6849
|
-
)
|
6850
|
-
tf_resources.append(
|
6842
|
+
),
|
6851
6843
|
Output(
|
6852
6844
|
output_prefix + "__bootstrap_brokers_tls",
|
6853
6845
|
value="${" + msk_cluster.bootstrap_brokers_tls + "}",
|
6854
|
-
)
|
6855
|
-
)
|
6856
|
-
tf_resources.append(
|
6846
|
+
),
|
6857
6847
|
Output(
|
6858
6848
|
output_prefix + "__bootstrap_brokers_sasl_iam",
|
6859
6849
|
value="${" + msk_cluster.bootstrap_brokers_sasl_iam + "}",
|
6860
|
-
)
|
6861
|
-
)
|
6862
|
-
tf_resources.append(
|
6850
|
+
),
|
6863
6851
|
Output(
|
6864
6852
|
output_prefix + "__bootstrap_brokers_sasl_scram",
|
6865
6853
|
value="${" + msk_cluster.bootstrap_brokers_sasl_scram + "}",
|
6866
|
-
)
|
6867
|
-
|
6854
|
+
),
|
6855
|
+
]
|
6868
6856
|
self.add_resources(account, tf_resources)
|
6869
6857
|
|
6870
6858
|
def populate_saml_idp(self, account_name: str, name: str, metadata: str) -> None:
|
reconcile/utils/vault.py
CHANGED
@@ -222,7 +222,7 @@ class _VaultClient:
|
|
222
222
|
mount_point = path_split[0]
|
223
223
|
read_path = "/".join(path_split[1:])
|
224
224
|
if version is None:
|
225
|
-
msg = "version can not be null
|
225
|
+
msg = f"version can not be null for secret with path '{path}'."
|
226
226
|
raise SecretVersionIsNone(msg)
|
227
227
|
if version == SECRET_VERSION_LATEST:
|
228
228
|
# https://github.com/hvac/hvac/blob/
|
@@ -236,7 +236,7 @@ class _VaultClient:
|
|
236
236
|
version=version,
|
237
237
|
)
|
238
238
|
except InvalidPath:
|
239
|
-
msg = f"version '{version}' not found
|
239
|
+
msg = f"version '{version}' not found for secret with path '{path}'."
|
240
240
|
raise SecretVersionNotFound(msg) from None
|
241
241
|
except hvac.exceptions.Forbidden:
|
242
242
|
msg = f"permission denied accessing secret '{path}'"
|
reconcile/utils/vcs.py
CHANGED
@@ -70,25 +70,17 @@ class VCS:
|
|
70
70
|
self._allow_opening_mrs = allow_opening_mrs
|
71
71
|
self._secret_reader = secret_reader
|
72
72
|
self._gh_per_repo_url: dict[str, GithubRepositoryApi] = (
|
73
|
-
github_api_per_repo_url
|
73
|
+
github_api_per_repo_url or {}
|
74
74
|
)
|
75
|
-
self._default_gh_token = (
|
76
|
-
|
77
|
-
if default_gh_token
|
78
|
-
else self._get_default_gh_token(github_orgs=github_orgs)
|
75
|
+
self._default_gh_token = default_gh_token or self._get_default_gh_token(
|
76
|
+
github_orgs=github_orgs
|
79
77
|
)
|
80
|
-
self._gitlab_instance = (
|
81
|
-
|
82
|
-
if gitlab_instance
|
83
|
-
else self._gitlab_api(gitlab_instances=gitlab_instances)
|
78
|
+
self._gitlab_instance = gitlab_instance or self._gitlab_api(
|
79
|
+
gitlab_instances=gitlab_instances
|
84
80
|
)
|
85
|
-
self._app_interface_api = (
|
86
|
-
|
87
|
-
|
88
|
-
else self._init_app_interface_api(
|
89
|
-
gitlab_instances=gitlab_instances,
|
90
|
-
app_interface_repo_url=app_interface_repo_url,
|
91
|
-
)
|
81
|
+
self._app_interface_api = app_interface_api or self._init_app_interface_api(
|
82
|
+
gitlab_instances=gitlab_instances,
|
83
|
+
app_interface_repo_url=app_interface_repo_url,
|
92
84
|
)
|
93
85
|
self._is_commit_sha_regex = re.compile(r"^[0-9a-f]{40}$")
|
94
86
|
|
reconcile/vault_replication.py
CHANGED
@@ -197,14 +197,7 @@ def list_invalid_paths(
|
|
197
197
|
) -> list[str]:
|
198
198
|
"""Returns a list of paths that are listed to be copied are not present in the policy
|
199
199
|
to fail the integration if we are trying to copy secrets that are not allowed."""
|
200
|
-
|
201
|
-
invalid_paths = []
|
202
|
-
|
203
|
-
for path in path_list:
|
204
|
-
if not _policy_contains_path(path, policy_paths):
|
205
|
-
invalid_paths.append(path)
|
206
|
-
|
207
|
-
return invalid_paths
|
200
|
+
return [path for path in path_list if not _policy_contains_path(path, policy_paths)]
|
208
201
|
|
209
202
|
|
210
203
|
def _policy_contains_path(path: str, policy_paths: Iterable[str]) -> bool:
|
tools/app_interface_reporter.py
CHANGED
@@ -253,7 +253,7 @@ def get_apps_data(date, month_delta=1, thread_pool_size=10):
|
|
253
253
|
|
254
254
|
app_name = app["name"]
|
255
255
|
|
256
|
-
logging.info(f"collecting post-deploy jobs
|
256
|
+
logging.info(f"collecting post-deploy jobs information for {app_name}")
|
257
257
|
# this is now empty as it referred to post_deploy jobs via Jenkins. This section
|
258
258
|
# should be removed when we publish a new content format or if we get promotion data
|
259
259
|
# differently.
|
@@ -141,7 +141,7 @@ def _get_namespace_images(ns: NamespaceV1, oc_map: OCMap) -> NamespaceImages:
|
|
141
141
|
|
142
142
|
for c in containers:
|
143
143
|
if m := IMAGE_NAME_REGEX.match(c["image"]):
|
144
|
-
image_names.append(m.group("name"))
|
144
|
+
image_names.append(m.group("name")) # noqa: PERF401
|
145
145
|
except Exception as exc:
|
146
146
|
return NamespaceImages(
|
147
147
|
namespace_name=ns.name,
|
@@ -382,8 +382,10 @@ def render_app_cost(
|
|
382
382
|
if report.items:
|
383
383
|
cost_details_sections.append(item_cost_renderer(report=report, **kwargs))
|
384
384
|
if report.child_apps:
|
385
|
-
cost_details_sections
|
386
|
-
|
385
|
+
cost_details_sections += [
|
386
|
+
render_child_apps_cost(report),
|
387
|
+
render_total_cost(report),
|
388
|
+
]
|
387
389
|
cost_details = (
|
388
390
|
"\n".join(cost_details_sections) if cost_details_sections else "No data"
|
389
391
|
)
|
@@ -155,11 +155,7 @@ class GPGEncryptCommand:
|
|
155
155
|
command_data: GPGEncryptCommandData,
|
156
156
|
secret_reader: SecretReader | None = None,
|
157
157
|
) -> GPGEncryptCommand:
|
158
|
-
cls_secret_reader = (
|
159
|
-
secret_reader
|
160
|
-
if secret_reader
|
161
|
-
else SecretReader(settings=config.get_config())
|
162
|
-
)
|
158
|
+
cls_secret_reader = secret_reader or SecretReader(settings=config.get_config())
|
163
159
|
|
164
160
|
return cls(
|
165
161
|
command_data=command_data,
|
tools/qontract_cli.py
CHANGED
@@ -602,7 +602,7 @@ def ocm_fleet_upgrade_policies(
|
|
602
602
|
@click.option(
|
603
603
|
"--ignore-sts-clusters",
|
604
604
|
is_flag=True,
|
605
|
-
default=os.environ.get("IGNORE_STS_CLUSTERS"
|
605
|
+
default=bool(os.environ.get("IGNORE_STS_CLUSTERS")),
|
606
606
|
help="Ignore STS clusters",
|
607
607
|
)
|
608
608
|
@click.pass_context
|
@@ -1102,7 +1102,7 @@ def cidr_blocks(ctx, for_cluster: int, mask: int) -> None:
|
|
1102
1102
|
"from": str(ipaddress.ip_network(cidr)[0]),
|
1103
1103
|
"to": str(ipaddress.ip_network(cidr)[-1]),
|
1104
1104
|
"hosts": str(ipaddress.ip_network(cidr).num_addresses),
|
1105
|
-
"description": f
|
1105
|
+
"description": f"CIDR {cidr} routed through account {connection['account']['name']} transit gateways",
|
1106
1106
|
}
|
1107
1107
|
for c in clusters
|
1108
1108
|
for connection in (c["peering"] or {}).get("connections") or []
|
@@ -1216,7 +1216,7 @@ def ocm_aws_infrastructure_access_switch_role_links(ctx):
|
|
1216
1216
|
for user in sorted(by_user.keys()):
|
1217
1217
|
print(f"- [{user}](#{user})")
|
1218
1218
|
for user in sorted(by_user.keys()):
|
1219
|
-
print(
|
1219
|
+
print()
|
1220
1220
|
print(f"# {user}")
|
1221
1221
|
print_output(ctx.obj["options"], by_user[user], columns)
|
1222
1222
|
|
@@ -1356,7 +1356,7 @@ def ocm_login(ctx, org_name):
|
|
1356
1356
|
client_secret = secret_reader.read(ocm["accessTokenClientSecret"])
|
1357
1357
|
access_token_command = f'curl -s -X POST {ocm["accessTokenUrl"]} -d "grant_type=client_credentials" -d "client_id={ocm["accessTokenClientId"]}" -d "client_secret={client_secret}" | jq -r .access_token'
|
1358
1358
|
print(
|
1359
|
-
f
|
1359
|
+
f"ocm login --url {ocm['environment']['url']} --token $({access_token_command})"
|
1360
1360
|
)
|
1361
1361
|
|
1362
1362
|
|
@@ -1607,7 +1607,7 @@ def jenkins_job_vault_secrets(ctx, instance_name: str, job_name: str) -> None:
|
|
1607
1607
|
secret_values = s["secret-values"]
|
1608
1608
|
for sv in secret_values:
|
1609
1609
|
print(
|
1610
|
-
f
|
1610
|
+
f'export {sv["env-var"]}="$(vault read -address={vault_url} -field={sv["vault-key"]} {secret_path})"'
|
1611
1611
|
)
|
1612
1612
|
|
1613
1613
|
|
@@ -1809,12 +1809,12 @@ def rds_recommendations(ctx):
|
|
1809
1809
|
continue
|
1810
1810
|
for spec in get_external_resource_specs(namespace_info):
|
1811
1811
|
if spec.provider == "rds":
|
1812
|
-
targetted_accounts.append(spec.provisioner_name)
|
1812
|
+
targetted_accounts.append(spec.provisioner_name) # noqa: PERF401
|
1813
1813
|
|
1814
1814
|
accounts = [
|
1815
1815
|
a for a in queries.get_aws_accounts() if a["name"] in targetted_accounts
|
1816
1816
|
]
|
1817
|
-
accounts.sort(key=
|
1817
|
+
accounts.sort(key=itemgetter("name"))
|
1818
1818
|
|
1819
1819
|
columns = [
|
1820
1820
|
# 'RecommendationId',
|
@@ -1865,7 +1865,7 @@ def rds_recommendations(ctx):
|
|
1865
1865
|
if not recommendations:
|
1866
1866
|
continue
|
1867
1867
|
# Sort by ResourceName
|
1868
|
-
recommendations.sort(key=
|
1868
|
+
recommendations.sort(key=itemgetter("ResourceName"))
|
1869
1869
|
|
1870
1870
|
print(f"# {account_name} - {region}")
|
1871
1871
|
print("Note: Severity informational is not shown.")
|
@@ -2136,7 +2136,7 @@ def sre_checkpoints(ctx):
|
|
2136
2136
|
if (app["path"] not in parent_apps and app["onboardingStatus"] == "OnBoarded")
|
2137
2137
|
]
|
2138
2138
|
|
2139
|
-
checkpoints_data.sort(key=
|
2139
|
+
checkpoints_data.sort(key=itemgetter("latest"), reverse=True)
|
2140
2140
|
|
2141
2141
|
columns = ["name", "latest"]
|
2142
2142
|
print_output(ctx.obj["options"], checkpoints_data, columns)
|
@@ -2370,14 +2370,15 @@ def change_types(ctx) -> None:
|
|
2370
2370
|
for ss in r.self_service or []:
|
2371
2371
|
nr_files = len(ss.datafiles or []) + len(ss.resources or [])
|
2372
2372
|
usage_statistics[ss.change_type.name] += nr_files
|
2373
|
-
data = [
|
2374
|
-
|
2375
|
-
data.append({
|
2373
|
+
data = [
|
2374
|
+
{
|
2376
2375
|
"name": ct.name,
|
2377
2376
|
"description": ct.description,
|
2378
2377
|
"applicable to": f"{ct.context_type.value} {ct.context_schema or ''}",
|
2379
2378
|
"# usages": usage_statistics[ct.name],
|
2380
|
-
}
|
2379
|
+
}
|
2380
|
+
for ct in change_types
|
2381
|
+
]
|
2381
2382
|
columns = ["name", "description", "applicable to", "# usages"]
|
2382
2383
|
print_output(ctx.obj["options"], data, columns)
|
2383
2384
|
|
@@ -36,7 +36,7 @@ def build_channels(saas_files: Iterable[SaasFile]) -> list[Channel]:
|
|
36
36
|
auth_code = (
|
37
37
|
saas_file.authentication.code if saas_file.authentication else None
|
38
38
|
)
|
39
|
-
target_name = target.name
|
39
|
+
target_name = target.name or "NoName"
|
40
40
|
saas_target = SaasTarget(
|
41
41
|
app_name=saas_file.app.name,
|
42
42
|
repo_url=resource_template.url,
|
@@ -40,7 +40,7 @@ class SaasPromotionState:
|
|
40
40
|
continue
|
41
41
|
for publish_channel in target.promotion.publish or []:
|
42
42
|
if publish_channel == channel:
|
43
|
-
publisher_uids.append(
|
43
|
+
publisher_uids.append( # noqa: PERF401
|
44
44
|
target.uid(
|
45
45
|
parent_saas_file_name=saas_file.name,
|
46
46
|
parent_resource_template_name=resource_template.name,
|
tools/sd_app_sre_alert_report.py
CHANGED
@@ -48,7 +48,7 @@ def group_alerts(messages: list[dict]) -> dict[str, list[Alert]]:
|
|
48
48
|
for m in messages:
|
49
49
|
if "subtype" not in m or m["subtype"] != "bot_message":
|
50
50
|
logging.debug(
|
51
|
-
f
|
51
|
+
f"Skipping message '{m['text']}' as it does not come from a bot"
|
52
52
|
)
|
53
53
|
continue
|
54
54
|
|
@@ -65,7 +65,7 @@ def group_alerts(messages: list[dict]) -> dict[str, list[Alert]]:
|
|
65
65
|
alert_message = mg.group(3)
|
66
66
|
|
67
67
|
if not alert_name:
|
68
|
-
logging.debug(f
|
68
|
+
logging.debug(f"no alert name in title {at['title']}. Skipping")
|
69
69
|
continue
|
70
70
|
|
71
71
|
# If there's only one alert related to the alert_name, message will be part
|
@@ -104,7 +104,7 @@ def group_alerts(messages: list[dict]) -> dict[str, list[Alert]]:
|
|
104
104
|
elif "Alerts Resolved" in line:
|
105
105
|
alert_state = "RESOLVED"
|
106
106
|
elif line.startswith("-"):
|
107
|
-
mg = re.match("^- (.+)$", line)
|
107
|
+
mg = re.match(r"^- (.+)$", line)
|
108
108
|
if not mg:
|
109
109
|
continue
|
110
110
|
alert_message = mg.group(1)
|
{qontract_reconcile-0.10.2.dev14.dist-info → qontract_reconcile-0.10.2.dev15.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|