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
reconcile/acs_rbac.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import logging
2
2
  from collections import defaultdict
3
3
  from collections.abc import Callable
4
+ from itertools import starmap
4
5
  from typing import (
5
6
  Self,
6
7
  )
@@ -151,10 +152,7 @@ class AcsRbacIntegration(QontractReconcileIntegration[NoParams]):
151
152
  permission_usernames[
152
153
  Permission(**permission.dict(by_alias=True))
153
154
  ].append(user.org_username)
154
- return [
155
- AcsRole.build(permission, usernames)
156
- for permission, usernames in permission_usernames.items()
157
- ]
155
+ return list(starmap(AcsRole.build, permission_usernames.items()))
158
156
 
159
157
  def get_current_state(
160
158
  self, auth_provider_id: str, rbac_api_resources: RbacResources
reconcile/aus/base.py CHANGED
@@ -585,20 +585,20 @@ def fetch_current_state(
585
585
  addon_upgrade_policies = addon_service.get_addon_upgrade_policies(
586
586
  ocm_api, spec.cluster.id, addon_id=addon_spec.addon.addon.id
587
587
  )
588
- for addon_upgrade_policy in addon_upgrade_policies:
589
- current_state.append(
590
- AddonUpgradePolicy(
591
- id=addon_upgrade_policy.id,
592
- addon_id=addon_spec.addon.addon.id,
593
- cluster=spec.cluster,
594
- next_run=addon_upgrade_policy.next_run,
595
- schedule=addon_upgrade_policy.schedule,
596
- schedule_type=addon_upgrade_policy.schedule_type,
597
- version=addon_upgrade_policy.version,
598
- state=addon_upgrade_policy.state,
599
- addon_service=addon_service,
600
- )
588
+ current_state.extend(
589
+ AddonUpgradePolicy(
590
+ id=addon_upgrade_policy.id,
591
+ addon_id=addon_spec.addon.addon.id,
592
+ cluster=spec.cluster,
593
+ next_run=addon_upgrade_policy.next_run,
594
+ schedule=addon_upgrade_policy.schedule,
595
+ schedule_type=addon_upgrade_policy.schedule_type,
596
+ version=addon_upgrade_policy.version,
597
+ state=addon_upgrade_policy.state,
598
+ addon_service=addon_service,
601
599
  )
600
+ for addon_upgrade_policy in addon_upgrade_policies
601
+ )
602
602
  elif spec.cluster.is_rosa_hypershift():
603
603
  upgrade_policies = get_control_plane_upgrade_policies(
604
604
  ocm_api, spec.cluster.id
@@ -19,8 +19,7 @@ def filter_accounts(accounts: Iterable[dict[str, Any]]) -> list[dict[str, Any]]:
19
19
  sharing = a.get("sharing")
20
20
  if sharing:
21
21
  sharing_account_names.add(a["name"])
22
- for s in sharing:
23
- sharing_account_names.add(s["account"]["name"])
22
+ sharing_account_names.update(s["account"]["name"] for s in sharing)
24
23
 
25
24
  return [a for a in accounts if a["name"] in sharing_account_names]
26
25
 
@@ -35,7 +35,7 @@ class AWSCloudwatchCleanupOption(BaseModel):
35
35
 
36
36
 
37
37
  DEFAULT_AWS_CLOUDWATCH_CLEANUP_OPTION = AWSCloudwatchCleanupOption(
38
- regex=re.compile(".*"),
38
+ regex=re.compile(r".*"),
39
39
  retention_in_days=DEFAULT_RETENTION_IN_DAYS,
40
40
  delete_empty_log_group=False,
41
41
  )
@@ -177,7 +177,7 @@ class AwsSamlIdpIntegration(QontractReconcileIntegration[AwsSamlIdpIntegrationPa
177
177
  integration_version=QONTRACT_INTEGRATION_VERSION,
178
178
  dry_run=dry_run,
179
179
  cache_source=ts.terraform_configurations(),
180
- shard=self.params.account_name if self.params.account_name else "",
180
+ shard=self.params.account_name or "",
181
181
  ttl_seconds=self.params.extended_early_exit_cache_ttl_seconds,
182
182
  logger=logging.getLogger(),
183
183
  runner=runner,
@@ -295,7 +295,7 @@ class AwsSamlRolesIntegration(
295
295
  integration_version=QONTRACT_INTEGRATION_VERSION,
296
296
  dry_run=dry_run,
297
297
  cache_source=ts.terraform_configurations(),
298
- shard=self.params.account_name if self.params.account_name else "",
298
+ shard=self.params.account_name or "",
299
299
  ttl_seconds=self.params.extended_early_exit_cache_ttl_seconds,
300
300
  logger=logging.getLogger(),
301
301
  runner=runner,
@@ -273,7 +273,7 @@ class AVSIntegration(QontractReconcileIntegration[AVSIntegrationParams]):
273
273
  supported_providers: Iterable[str],
274
274
  ) -> list[ExternalResource]:
275
275
  external_resources: list[ExternalResource] = []
276
- _defaults_cache: dict[str, Any] = {}
276
+ defaults_cache: dict[str, Any] = {}
277
277
  for ns in namespaces:
278
278
  for external_resource in ns.external_resources or []:
279
279
  if not isinstance(
@@ -297,12 +297,12 @@ class AVSIntegration(QontractReconcileIntegration[AVSIntegrationParams]):
297
297
  values = {}
298
298
  # get/set the defaults file values from/to cache
299
299
  if resource.defaults:
300
- if not (values := _defaults_cache.get(resource.defaults, {})):
300
+ if not (values := defaults_cache.get(resource.defaults, {})):
301
301
  # retrieve the external resource spec values
302
302
  values = get_values(
303
303
  gql_get_resource_func, resource.defaults
304
304
  )
305
- _defaults_cache[resource.defaults] = values
305
+ defaults_cache[resource.defaults] = values
306
306
  values = override_values(values, resource.overrides)
307
307
  if resource.provider.lower() == "elasticache" and str(
308
308
  values["engine_version"]
@@ -215,8 +215,8 @@ def write_coverage_report_to_stdout(change_decisions: list[ChangeDecision]) -> N
215
215
  "disabled": False,
216
216
  })
217
217
  if d.coverage:
218
- for ctx in d.coverage:
219
- results.append({
218
+ results.extend(
219
+ {
220
220
  "file": d.file.path,
221
221
  "schema": d.file.schema,
222
222
  "changed path": d.diff.path,
@@ -228,7 +228,9 @@ def write_coverage_report_to_stdout(change_decisions: list[ChangeDecision]) -> N
228
228
  for ar in ctx.approver_reachability or []
229
229
  ]),
230
230
  "disabled": str(ctx.disabled),
231
- })
231
+ }
232
+ for ctx in d.coverage
233
+ )
232
234
  else:
233
235
  results.append({
234
236
  "file": d.file.path,
@@ -453,8 +455,9 @@ def run(
453
455
  if not co_label.startswith("change-owner/")
454
456
  }
455
457
  for bc in changes:
456
- for label in bc.change_owner_labels:
457
- labels.add(change_owner_label(label))
458
+ labels.update(
459
+ change_owner_label(label) for label in bc.change_owner_labels
460
+ )
458
461
 
459
462
  if mr_management_enabled:
460
463
  gl.set_labels_on_merge_request(merge_request, labels)
@@ -578,15 +578,15 @@ class ChangeTypeProcessor:
578
578
 
579
579
  # expand context based on change-type composition
580
580
  for ce in self._context_expansions:
581
- for ec in ce.expand(change, expansion_trail_copy):
582
- # add expanded contexts (derived owned files)
583
- contexts.append(
584
- ResolvedContext(
585
- owned_file_ref=ec.owned_file_ref,
586
- context_file_ref=change.file_ref,
587
- change_type=ec.change_type,
588
- )
581
+ # add expanded contexts (derived owned files)
582
+ contexts.extend(
583
+ ResolvedContext(
584
+ owned_file_ref=ec.owned_file_ref,
585
+ context_file_ref=change.file_ref,
586
+ change_type=ec.change_type,
589
587
  )
588
+ for ec in ce.expand(change, expansion_trail_copy)
589
+ )
590
590
 
591
591
  # context detection
592
592
  # the context for approver extraction can be found within the changed
@@ -603,17 +603,17 @@ class ChangeTypeProcessor:
603
603
  )
604
604
  )
605
605
  for ce in self._context_expansions:
606
- for ec in ce.expand_from_file_ref(
607
- ctx_file_ref, expansion_trail_copy
608
- ):
609
- # add expanded contexts (derived owned files)
610
- contexts.append(
611
- ResolvedContext(
612
- owned_file_ref=ec.owned_file_ref,
613
- context_file_ref=ctx_file_ref,
614
- change_type=ec.change_type,
615
- )
606
+ # add expanded contexts (derived owned files)
607
+ contexts.extend(
608
+ ResolvedContext(
609
+ owned_file_ref=ec.owned_file_ref,
610
+ context_file_ref=ctx_file_ref,
611
+ change_type=ec.change_type,
612
+ )
613
+ for ec in ce.expand_from_file_ref(
614
+ ctx_file_ref, expansion_trail_copy
616
615
  )
616
+ )
617
617
 
618
618
  return contexts
619
619
 
@@ -211,11 +211,11 @@ class BundleFileChange:
211
211
  returns all the change-types that are involved in the coverage
212
212
  of all changes
213
213
  """
214
- change_types = []
215
- for dc in self.diff_coverage:
216
- for ctx in dc.coverage:
217
- change_types.append(ctx.change_type_processor)
218
- return change_types
214
+ return [
215
+ ctx.change_type_processor
216
+ for dc in self.diff_coverage
217
+ for ctx in dc.coverage
218
+ ]
219
219
 
220
220
 
221
221
  def parse_resource_file_content(content: Any | None) -> tuple[Any, str | None]:
@@ -308,10 +308,9 @@ def get_priority_for_changes(
308
308
  """
309
309
  Finds the lowest priority of all change types involved in the provided bundle file changes.
310
310
  """
311
- priorities: set[ChangeTypePriority] = set()
312
- for bfc in bundle_file_changes:
313
- for ct in bfc.involved_change_types():
314
- priorities.add(ct.priority)
311
+ priorities = {
312
+ ct.priority for bfc in bundle_file_changes for ct in bfc.involved_change_types()
313
+ }
315
314
  # get the lowest priority
316
315
  for p in reversed(ChangeTypePriority):
317
316
  if p in priorities:
@@ -1,3 +1,4 @@
1
+ import operator
1
2
  from collections import defaultdict
2
3
  from collections.abc import (
3
4
  Iterable,
@@ -35,7 +36,7 @@ def get_approver_decisions_from_mr_comments(
35
36
  comments: Iterable[Mapping[str, Any]],
36
37
  ) -> list[Decision]:
37
38
  decisions: list[Decision] = []
38
- for c in sorted(comments, key=lambda k: k["created_at"]):
39
+ for c in sorted(comments, key=operator.itemgetter("created_at")):
39
40
  commenter = c["username"]
40
41
  comment_body = c.get("body")
41
42
  for line in comment_body.split("\n") if comment_body else []:
@@ -146,20 +147,16 @@ def apply_decisions_to_changes(
146
147
  to generate the coverage report and to reason about the approval
147
148
  state of the MR.
148
149
  """
149
-
150
- diff_decisions = []
151
- for c in changes:
152
- for d in c.diff_coverage:
153
- diff_decisions.append(
154
- _apply_decision_to_diff(
155
- c,
156
- d,
157
- approver_decisions,
158
- auto_approver_usernames,
159
- )
160
- )
161
-
162
- return diff_decisions
150
+ return [
151
+ _apply_decision_to_diff(
152
+ c,
153
+ d,
154
+ approver_decisions,
155
+ auto_approver_usernames,
156
+ )
157
+ for c in changes
158
+ for d in c.diff_coverage
159
+ ]
163
160
 
164
161
 
165
162
  def _apply_decision_to_diff(
@@ -139,7 +139,7 @@ def change_type_contexts_for_self_service_roles(
139
139
  resolved_approvers = resolve_role_members([r for r in roles if r.self_service])
140
140
 
141
141
  # match every BundleChange with every relevant ChangeTypeV1
142
- change_type_contexts = []
142
+ change_type_contexts: list[tuple[BundleFileChange, ChangeTypeContext]] = []
143
143
  for bc in bundle_changes:
144
144
  for ctp in change_type_processors:
145
145
  for ownership in ctp.find_context_file_refs(
@@ -177,8 +177,8 @@ def change_type_contexts_for_self_service_roles(
177
177
  else []
178
178
  )
179
179
  })
180
- for role in owning_roles.values():
181
- change_type_contexts.append((
180
+ change_type_contexts.extend(
181
+ (
182
182
  bc,
183
183
  ChangeTypeContext(
184
184
  change_type_processor=ctp,
@@ -193,7 +193,9 @@ def change_type_contexts_for_self_service_roles(
193
193
  change_owner_labels=change_type_labels_from_role(role),
194
194
  context_file=ownership.context_file_ref,
195
195
  ),
196
- ))
196
+ )
197
+ for role in owning_roles.values()
198
+ )
197
199
  return change_type_contexts
198
200
 
199
201
 
@@ -130,16 +130,14 @@ class AppInterfaceRepo:
130
130
  elif c.change_schema is None or c.change_schema == ctp.context_schema:
131
131
  # the change happens in the self_service related files
132
132
  for ssc in role.self_service or []:
133
- for df in ssc.datafiles or []:
134
- bundle_files.append(
135
- self.bundle_file_for_path(BundleFileType.DATAFILE, df.path)
136
- )
137
- for rf_path in ssc.resources or []:
138
- bundle_files.append(
139
- self.bundle_file_for_path(
140
- BundleFileType.RESOURCEFILE, rf_path
141
- )
142
- )
133
+ bundle_files.extend(
134
+ self.bundle_file_for_path(BundleFileType.DATAFILE, df.path)
135
+ for df in ssc.datafiles or []
136
+ )
137
+ bundle_files.extend(
138
+ self.bundle_file_for_path(BundleFileType.RESOURCEFILE, rf_path)
139
+ for rf_path in ssc.resources or []
140
+ )
143
141
  return bundle_files
144
142
 
145
143
  def bundle_files_with_schemas(self, schema: str) -> list[BundleFileChange]:
reconcile/cli.py CHANGED
@@ -256,7 +256,7 @@ def print_to_file(function):
256
256
  def config_name(function):
257
257
  function = click.option(
258
258
  "--config-name",
259
- help="jenkins config name to print out." "must works with --print-only mode",
259
+ help="jenkins config name to print out.must works with --print-only mode",
260
260
  default=None,
261
261
  )(function)
262
262
 
@@ -308,7 +308,7 @@ def vault_output_path(function):
308
308
  def vault_throughput_path(function):
309
309
  function = click.option(
310
310
  "--vault-throughput-path",
311
- help="path in Vault to find input resources " "and store output resources.",
311
+ help="path in Vault to find input resources and store output resources.",
312
312
  default="",
313
313
  )(function)
314
314
 
@@ -888,7 +888,7 @@ def openshift_users(ctx, thread_pool_size, internal, use_jump_host):
888
888
 
889
889
 
890
890
  @integration.command(
891
- short_help="Use OpenShift ServiceAccount tokens " "across namespaces/clusters."
891
+ short_help="Use OpenShift ServiceAccount tokens across namespaces/clusters."
892
892
  )
893
893
  @threaded()
894
894
  @binary(["oc", "ssh"])
@@ -1601,8 +1601,7 @@ def openshift_tekton_resources(
1601
1601
 
1602
1602
 
1603
1603
  @integration.command(
1604
- short_help="Guesses and adds labels to merge requests "
1605
- "according to changed paths."
1604
+ short_help="Guesses and adds labels to merge requests according to changed paths."
1606
1605
  )
1607
1606
  @click.argument("gitlab-project-id")
1608
1607
  @click.argument("gitlab-merge-request-id")
@@ -2801,7 +2800,7 @@ def ocm_addons_upgrade_scheduler_org(
2801
2800
  @click.option(
2802
2801
  "--ignore-sts-clusters",
2803
2802
  is_flag=True,
2804
- default=os.environ.get("IGNORE_STS_CLUSTERS", False),
2803
+ default=bool(os.environ.get("IGNORE_STS_CLUSTERS")),
2805
2804
  help="Ignore STS clusters",
2806
2805
  )
2807
2806
  @click.pass_context
@@ -2938,7 +2937,7 @@ def ocm_addons(ctx, thread_pool_size):
2938
2937
 
2939
2938
 
2940
2939
  @integration.command(
2941
- short_help="Grants AWS infrastructure access " "to members in AWS groups via OCM."
2940
+ short_help="Grants AWS infrastructure access to members in AWS groups via OCM."
2942
2941
  )
2943
2942
  @click.pass_context
2944
2943
  def ocm_aws_infrastructure_access(ctx):
@@ -3129,7 +3128,7 @@ def email_sender(ctx):
3129
3128
 
3130
3129
 
3131
3130
  @integration.command(
3132
- short_help="Send emails to users based on " "requests submitted to app-interface."
3131
+ short_help="Send emails to users based on requests submitted to app-interface."
3133
3132
  )
3134
3133
  @click.pass_context
3135
3134
  def requests_sender(ctx):
@@ -3156,8 +3155,7 @@ def sql_query(ctx, enable_deletion):
3156
3155
 
3157
3156
 
3158
3157
  @integration.command(
3159
- short_help="Manages labels on gitlab merge requests "
3160
- "based on OWNERS files schema."
3158
+ short_help="Manages labels on gitlab merge requests based on OWNERS files schema."
3161
3159
  )
3162
3160
  @threaded()
3163
3161
  @click.pass_context
@@ -3525,7 +3523,7 @@ def integrations_manager(
3525
3523
  @click.option(
3526
3524
  "--mr-management",
3527
3525
  is_flag=True,
3528
- default=os.environ.get("MR_MANAGEMENT", False),
3526
+ default=bool(os.environ.get("MR_MANAGEMENT")),
3529
3527
  help="Manage MR labels and comments (default to false)",
3530
3528
  )
3531
3529
  @click.pass_context
@@ -84,7 +84,7 @@ def parse_prober_url(url: str) -> dict[str, str]:
84
84
  parsed_url = urlparse(url)
85
85
  if parsed_url.scheme not in {"http", "https"}:
86
86
  raise ValueError(
87
- "the prober URL needs to be an http:// or https:// one " f"but is {url}"
87
+ f"the prober URL needs to be an http:// or https:// one but is {url}"
88
88
  )
89
89
  data = {"url": parsed_url.netloc, "scheme": parsed_url.scheme}
90
90
  if parsed_url.path:
@@ -49,8 +49,8 @@ class CNAIntegration:
49
49
  ):
50
50
  self._cna_clients = cna_clients
51
51
  self._namespaces = namespaces
52
- self._desired_states = desired_states if desired_states else defaultdict(State)
53
- self._current_states = current_states if current_states else defaultdict(State)
52
+ self._desired_states = desired_states or defaultdict(State)
53
+ self._current_states = current_states or defaultdict(State)
54
54
 
55
55
  def assemble_desired_states(self):
56
56
  self._desired_states = defaultdict(State)
@@ -57,7 +57,7 @@ class DashdotdbBase:
57
57
  return None
58
58
 
59
59
  params = {"scope": self.scope}
60
- endpoint = f"{self.dashdotdb_url}/api/v1/" f"token"
60
+ endpoint = f"{self.dashdotdb_url}/api/v1/token"
61
61
  response = requests.get(
62
62
  url=endpoint,
63
63
  params=params,
@@ -81,7 +81,7 @@ class DashdotdbBase:
81
81
  return None
82
82
 
83
83
  params = {"scope": self.scope}
84
- endpoint = f"{self.dashdotdb_url}/api/v1/" f"token/{self.dashdotdb_token}"
84
+ endpoint = f"{self.dashdotdb_url}/api/v1/token/{self.dashdotdb_token}"
85
85
  response = requests.delete(
86
86
  url=endpoint,
87
87
  params=params,
@@ -56,7 +56,7 @@ class DashdotdbCSO(DashdotdbBase):
56
56
  return response
57
57
 
58
58
  for item in imagemanifestvuln["items"]:
59
- endpoint = f"{self.dashdotdb_url}/api/v1/" f"imagemanifestvuln/{cluster}"
59
+ endpoint = f"{self.dashdotdb_url}/api/v1/imagemanifestvuln/{cluster}"
60
60
  response = self._do_post(endpoint, item)
61
61
  try:
62
62
  response.raise_for_status()
@@ -110,7 +110,7 @@ class DeploymentDB:
110
110
  trigger_reason_pattern: str,
111
111
  app_env_since_list: Iterable[tuple[AppEnv, datetime]],
112
112
  ) -> list[tuple[AppEnv, Deployment]]:
113
- deployments = []
113
+ deployments: list[tuple[AppEnv, Deployment]] = []
114
114
  with self.conn.cursor() as cur:
115
115
  subq = [
116
116
  sql.SQL(
@@ -137,11 +137,13 @@ class DeploymentDB:
137
137
 
138
138
  cur.execute(query)
139
139
 
140
- for record in cur:
141
- deployments.append((
140
+ deployments.extend(
141
+ (
142
142
  AppEnv(record[0], record[1]),
143
143
  Deployment(record[2], record[3]),
144
- ))
144
+ )
145
+ for record in cur
146
+ )
145
147
 
146
148
  if not deployments:
147
149
  LOG.info("No deployments found")
@@ -78,7 +78,7 @@ class DashdotdbSLO(DashdotdbBase):
78
78
 
79
79
  for item in service_slos:
80
80
  slo_name = item.name
81
- endpoint = f"{self.dashdotdb_url}/api/v1/" f"serviceslometrics/{slo_name}"
81
+ endpoint = f"{self.dashdotdb_url}/api/v1/serviceslometrics/{slo_name}"
82
82
  payload = item.dashdot_payload()
83
83
  if self.dry_run:
84
84
  continue
@@ -127,7 +127,7 @@ DROP ROLE IF EXISTS "{self._get_user()}";\\gexec"""
127
127
 
128
128
  def _generate_db_access(self) -> str:
129
129
  statements = [
130
- f"GRANT {','.join(access.grants)} ON ALL TABLES IN SCHEMA \"{access.target.dbschema}\" TO \"{self._get_user()}\";"
130
+ f'GRANT {",".join(access.grants)} ON ALL TABLES IN SCHEMA "{access.target.dbschema}" TO "{self._get_user()}";'
131
131
  for access in self.db_access.access or []
132
132
  ]
133
133
  return "\n".join(statements)
@@ -149,10 +149,10 @@ DROP ROLE IF EXISTS "{self._get_user()}";\\gexec"""
149
149
  f'REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA "{schema}" FROM "{self._get_user()}";'
150
150
  )
151
151
  else:
152
- for grant in set(grants) - set(desired_grants[schema]):
153
- statements.append(
154
- f'REVOKE {grant} ON ALL TABLES IN SCHEMA "{schema}" FROM "{self._get_user()}";'
155
- )
152
+ statements.extend(
153
+ f'REVOKE {grant} ON ALL TABLES IN SCHEMA "{schema}" FROM "{self._get_user()}";'
154
+ for grant in set(grants) - set(desired_grants[schema])
155
+ )
156
156
  return "".join(statements)
157
157
 
158
158
  def _provision_script(self) -> str:
@@ -445,22 +445,20 @@ def _populate_resources(
445
445
  engine=engine,
446
446
  )
447
447
  script_secret_name = f"{resource_prefix}-script"
448
- managed_resources.append(
448
+ managed_resources.extend([
449
449
  DBAMResource(
450
450
  resource=generate_script_secret_spec(
451
451
  script_secret_name,
452
452
  generator.generate_script(),
453
453
  ),
454
454
  clean_up=True,
455
- )
456
- )
457
- # create user secret
458
- managed_resources.append(
455
+ ),
456
+ # create user secret
459
457
  DBAMResource(
460
458
  resource=generate_user_secret_spec(resource_prefix, user_connection),
461
459
  clean_up=False,
462
- )
463
- )
460
+ ),
461
+ ])
464
462
  # create pull secret
465
463
  labels = pull_secret["labels"] or {}
466
464
  pull_secret_resources = orb.fetch_provider_vault_secret(
@@ -474,11 +472,9 @@ def _populate_resources(
474
472
  integration_version=QONTRACT_INTEGRATION_VERSION,
475
473
  settings=settings,
476
474
  )
477
- managed_resources.append(
478
- DBAMResource(resource=pull_secret_resources, clean_up=True)
479
- )
480
- # create job
481
- managed_resources.append(
475
+ managed_resources.extend([
476
+ DBAMResource(resource=pull_secret_resources, clean_up=True),
477
+ # create job
482
478
  DBAMResource(
483
479
  resource=get_job_spec(
484
480
  JobData(
@@ -493,8 +489,8 @@ def _populate_resources(
493
489
  )
494
490
  ),
495
491
  clean_up=True,
496
- )
497
- )
492
+ ),
493
+ ])
498
494
 
499
495
  return managed_resources
500
496
 
reconcile/email_sender.py CHANGED
@@ -53,8 +53,7 @@ def collect_to(to):
53
53
  if not service_owners:
54
54
  continue
55
55
 
56
- for service_owner in service_owners:
57
- audience.add(service_owner["email"])
56
+ audience.update(service_owner["email"] for service_owner in service_owners)
58
57
 
59
58
  # TODO: implement clusters and namespaces
60
59
 
@@ -65,8 +64,7 @@ def collect_to(to):
65
64
  if not account_owners:
66
65
  continue
67
66
 
68
- for account_owner in account_owners:
69
- audience.add(account_owner["email"])
67
+ audience.update(account_owner["email"] for account_owner in account_owners)
70
68
 
71
69
  roles = to.get("roles")
72
70
  if roles:
@@ -75,13 +73,11 @@ def collect_to(to):
75
73
  if not users:
76
74
  continue
77
75
 
78
- for user in users:
79
- audience.add(user["org_username"])
76
+ audience.update(user["org_username"] for user in users)
80
77
 
81
78
  users = to.get("users")
82
79
  if users:
83
- for user in users:
84
- audience.add(user["org_username"])
80
+ audience.update(user["org_username"] for user in users)
85
81
 
86
82
  return audience
87
83
 
@@ -120,8 +120,8 @@ class OutputSecretsFormatter:
120
120
  def _format_value(self, value: str) -> str:
121
121
  decoded_value = base64.b64decode(value).decode("utf-8")
122
122
  if decoded_value.startswith("__vault__:"):
123
- _secret_ref = json.loads(decoded_value.replace("__vault__:", ""))
124
- secret_ref = VaultSecret(**_secret_ref)
123
+ secret_ref_ = json.loads(decoded_value.replace("__vault__:", ""))
124
+ secret_ref = VaultSecret(**secret_ref_)
125
125
  return self.secret_reader.read_secret(secret_ref)
126
126
  else:
127
127
  return decoded_value