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.
Files changed (133) hide show
  1. {qontract_reconcile-0.10.2.dev14.dist-info → qontract_reconcile-0.10.2.dev15.dist-info}/METADATA +1 -1
  2. {qontract_reconcile-0.10.2.dev14.dist-info → qontract_reconcile-0.10.2.dev15.dist-info}/RECORD +133 -133
  3. reconcile/acs_rbac.py +2 -4
  4. reconcile/aus/base.py +13 -13
  5. reconcile/aws_ami_share.py +1 -2
  6. reconcile/aws_cloudwatch_log_retention/integration.py +1 -1
  7. reconcile/aws_saml_idp/integration.py +1 -1
  8. reconcile/aws_saml_roles/integration.py +1 -1
  9. reconcile/aws_version_sync/integration.py +3 -3
  10. reconcile/change_owners/change_owners.py +8 -5
  11. reconcile/change_owners/change_types.py +18 -18
  12. reconcile/change_owners/changes.py +8 -9
  13. reconcile/change_owners/decision.py +12 -15
  14. reconcile/change_owners/self_service_roles.py +6 -4
  15. reconcile/change_owners/tester.py +8 -10
  16. reconcile/cli.py +9 -11
  17. reconcile/closedbox_endpoint_monitoring_base.py +1 -1
  18. reconcile/cna/integration.py +2 -2
  19. reconcile/dashdotdb_base.py +2 -2
  20. reconcile/dashdotdb_cso.py +1 -1
  21. reconcile/dashdotdb_dora.py +6 -4
  22. reconcile/dashdotdb_slo.py +1 -1
  23. reconcile/database_access_manager.py +15 -19
  24. reconcile/email_sender.py +4 -8
  25. reconcile/external_resources/secrets_sync.py +2 -2
  26. reconcile/external_resources/state.py +17 -17
  27. reconcile/gabi_authorized_users.py +3 -3
  28. reconcile/gcr_mirror.py +2 -2
  29. reconcile/github_org.py +9 -13
  30. reconcile/gitlab_housekeeping.py +1 -1
  31. reconcile/gitlab_owners.py +10 -12
  32. reconcile/gitlab_permissions.py +5 -4
  33. reconcile/glitchtip/integration.py +14 -14
  34. reconcile/glitchtip_project_alerts/integration.py +3 -4
  35. reconcile/integrations_manager.py +1 -2
  36. reconcile/jenkins_job_builds_cleaner.py +7 -5
  37. reconcile/jenkins_roles.py +10 -6
  38. reconcile/jenkins_worker_fleets.py +5 -4
  39. reconcile/jira_permissions_validator.py +2 -6
  40. reconcile/ldap_groups/integration.py +3 -2
  41. reconcile/ocm_groups.py +5 -5
  42. reconcile/ocm_update_recommended_version.py +2 -2
  43. reconcile/openshift_base.py +15 -20
  44. reconcile/openshift_groups.py +9 -8
  45. reconcile/openshift_namespace_labels.py +3 -4
  46. reconcile/openshift_namespaces.py +1 -1
  47. reconcile/openshift_network_policies.py +1 -1
  48. reconcile/openshift_resources_base.py +4 -4
  49. reconcile/openshift_serviceaccount_tokens.py +1 -1
  50. reconcile/openshift_tekton_resources.py +1 -2
  51. reconcile/openshift_users.py +5 -4
  52. reconcile/prometheus_rules_tester/integration.py +8 -8
  53. reconcile/quay_mirror.py +3 -4
  54. reconcile/quay_mirror_org.py +1 -1
  55. reconcile/rhidp/ocm_oidc_idp/base.py +10 -15
  56. reconcile/run_integration.py +7 -7
  57. reconcile/saas_auto_promotions_manager/publisher.py +1 -1
  58. reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +3 -9
  59. reconcile/service_dependencies.py +2 -7
  60. reconcile/skupper_network/reconciler.py +5 -5
  61. reconcile/skupper_network/site_controller.py +3 -3
  62. reconcile/sql_query.py +5 -5
  63. reconcile/status_board.py +24 -24
  64. reconcile/terraform_cloudflare_users.py +2 -2
  65. reconcile/terraform_repo.py +6 -6
  66. reconcile/terraform_users.py +8 -5
  67. reconcile/terraform_vpc_peerings.py +1 -1
  68. reconcile/terraform_vpc_resources/integration.py +1 -1
  69. reconcile/typed_queries/app_interface_deadmanssnitch_settings.py +1 -1
  70. reconcile/typed_queries/app_quay_repos_escalation_policies.py +1 -1
  71. reconcile/typed_queries/aws_vpc_requests.py +1 -1
  72. reconcile/typed_queries/aws_vpcs.py +1 -1
  73. reconcile/typed_queries/clusters.py +1 -1
  74. reconcile/typed_queries/clusters_minimal.py +1 -1
  75. reconcile/typed_queries/clusters_with_dms.py +1 -1
  76. reconcile/typed_queries/dynatrace_environments.py +1 -1
  77. reconcile/typed_queries/dynatrace_token_provider_token_specs.py +1 -1
  78. reconcile/typed_queries/reserved_networks.py +1 -1
  79. reconcile/typed_queries/saas_files.py +1 -1
  80. reconcile/typed_queries/slo_documents.py +1 -1
  81. reconcile/typed_queries/status_board.py +1 -2
  82. reconcile/utils/amtool.py +2 -2
  83. reconcile/utils/aws_api.py +10 -10
  84. reconcile/utils/aws_helper.py +1 -1
  85. reconcile/utils/binary.py +1 -2
  86. reconcile/utils/differ.py +4 -7
  87. reconcile/utils/dnsutils.py +4 -12
  88. reconcile/utils/external_resources.py +1 -2
  89. reconcile/utils/gitlab_api.py +2 -4
  90. reconcile/utils/glitchtip/models.py +1 -1
  91. reconcile/utils/helm.py +1 -1
  92. reconcile/utils/instrumented_wrappers.py +2 -2
  93. reconcile/utils/jjb_client.py +1 -1
  94. reconcile/utils/jump_host.py +1 -1
  95. reconcile/utils/metrics.py +6 -11
  96. reconcile/utils/mr/aws_access.py +1 -1
  97. reconcile/utils/mr/base.py +2 -4
  98. reconcile/utils/mr/notificator.py +1 -1
  99. reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py +1 -1
  100. reconcile/utils/oc.py +17 -31
  101. reconcile/utils/oc_map.py +1 -1
  102. reconcile/utils/ocm/base.py +4 -2
  103. reconcile/utils/ocm/search_filters.py +4 -3
  104. reconcile/utils/ocm/status_board.py +2 -2
  105. reconcile/utils/ocm/upgrades.py +4 -7
  106. reconcile/utils/ocm_base_client.py +1 -1
  107. reconcile/utils/openshift_resource.py +1 -1
  108. reconcile/utils/promtool.py +1 -1
  109. reconcile/utils/quay_api.py +1 -3
  110. reconcile/utils/raw_github_api.py +3 -10
  111. reconcile/utils/repo_owners.py +5 -5
  112. reconcile/utils/rest_api_base.py +1 -2
  113. reconcile/utils/rosa/rosa_cli.py +3 -3
  114. reconcile/utils/saasherder/saasherder.py +9 -15
  115. reconcile/utils/secret_reader.py +2 -2
  116. reconcile/utils/sharding.py +2 -2
  117. reconcile/utils/state.py +5 -5
  118. reconcile/utils/terraform_client.py +2 -2
  119. reconcile/utils/terrascript/cloudflare_resources.py +4 -6
  120. reconcile/utils/terrascript_aws_client.py +16 -28
  121. reconcile/utils/vault.py +2 -2
  122. reconcile/utils/vcs.py +8 -16
  123. reconcile/vault_replication.py +1 -8
  124. tools/app_interface_reporter.py +1 -1
  125. tools/cli_commands/container_images_report.py +1 -1
  126. tools/cli_commands/cost_report/view.py +4 -2
  127. tools/cli_commands/gpg_encrypt.py +1 -5
  128. tools/qontract_cli.py +14 -13
  129. tools/saas_metrics_exporter/commit_distance/channel.py +1 -1
  130. tools/saas_promotion_state/saas_promotion_state.py +1 -1
  131. tools/sd_app_sre_alert_report.py +3 -3
  132. {qontract_reconcile-0.10.2.dev14.dist-info → qontract_reconcile-0.10.2.dev15.dist-info}/WHEEL +0 -0
  133. {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
 
@@ -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)
@@ -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
 
@@ -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
- _annotations = {
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
- _annotations.update(self.extra_annotations)
150
- return _annotations
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}] " f"missing allowedSecretParameterPaths section"
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 " "state only"
1869
+ "Promotion data is missing; rely on the success state only"
1876
1870
  )
1877
1871
  continue
1878
1872
 
@@ -163,7 +163,7 @@ class VaultSecretReader(SecretReaderBase):
163
163
  )
164
164
  except Forbidden:
165
165
  raise VaultForbidden(
166
- f"permission denied reading vault secret " f"at {path}"
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 " f"at {path}"
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
@@ -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 " f"exists in {self.state_path}")
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
- _current_value = self[key]
433
+ current_value = self[key]
434
434
  except KeyError:
435
- _current_value = None
436
- state_obj = TransactionStateObj(key, value=_current_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 != _current_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'{replica_src}-{tf_resource.get("provider")}'
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 _, wd in self.working_dirs.items():
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.append(
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_" f"{log_type.lower()}_arn"
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_" f"{log_type.lower()}_name"
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 " f"{identifier}"
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(str, common_values.get("region")) or 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'{common_values.get("api_proxy_uri")}/api/{{proxy}}',
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.append(
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 " f"for secret with path '{path}'."
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 " f"for secret with path '{path}'."
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 if github_api_per_repo_url else {}
73
+ github_api_per_repo_url or {}
74
74
  )
75
- self._default_gh_token = (
76
- default_gh_token
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
- gitlab_instance
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
- app_interface_api
87
- if app_interface_api
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
 
@@ -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:
@@ -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 " f"information for {app_name}")
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.append(render_child_apps_cost(report))
386
- cost_details_sections.append(render_total_cost(report))
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", False),
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'CIDR {cidr} routed through account {connection["account"]["name"]} transit gateways',
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'ocm login --url {ocm["environment"]["url"]} --token $({access_token_command})'
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"export {sv['env-var']}=\"$(vault read -address={vault_url} -field={sv['vault-key']} {secret_path})\""
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=lambda a: a["name"])
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=lambda r: r["ResourceName"])
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=lambda c: c["latest"], reverse=True)
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
- for ct in change_types:
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 if target.name else "NoName"
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,
@@ -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'Skipping message \'{m["text"]}\' as it does not come from a bot'
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'no alert name in title {at["title"]}. Skipping')
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)