qontract-reconcile 0.10.1rc884__py3-none-any.whl → 0.10.1rc886__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 (279) hide show
  1. {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/METADATA +1 -1
  2. {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/RECORD +279 -276
  3. reconcile/acs_rbac.py +1 -2
  4. reconcile/aus/advanced_upgrade_service.py +14 -14
  5. reconcile/aus/aus_label_source.py +1 -2
  6. reconcile/aus/base.py +23 -26
  7. reconcile/aus/cluster_version_data.py +4 -4
  8. reconcile/aus/models.py +2 -3
  9. reconcile/aus/version_gate_approver.py +2 -6
  10. reconcile/aus/version_gates/__init__.py +1 -3
  11. reconcile/aus/version_gates/sts_version_gate_handler.py +2 -3
  12. reconcile/aws_account_manager/integration.py +2 -2
  13. reconcile/aws_ami_cleanup/integration.py +3 -4
  14. reconcile/aws_iam_password_reset.py +2 -5
  15. reconcile/aws_version_sync/integration.py +2 -2
  16. reconcile/blackbox_exporter_endpoint_monitoring.py +2 -5
  17. reconcile/change_owners/approver.py +4 -5
  18. reconcile/change_owners/bundle.py +20 -22
  19. reconcile/change_owners/change_types.py +23 -24
  20. reconcile/change_owners/changes.py +13 -16
  21. reconcile/change_owners/decision.py +2 -5
  22. reconcile/change_owners/diff.py +11 -15
  23. reconcile/change_owners/self_service_roles.py +1 -2
  24. reconcile/change_owners/tester.py +7 -10
  25. reconcile/checkpoint.py +2 -5
  26. reconcile/cli.py +9 -12
  27. reconcile/closedbox_endpoint_monitoring_base.py +8 -11
  28. reconcile/cluster_deployment_mapper.py +2 -5
  29. reconcile/cna/assets/asset.py +4 -7
  30. reconcile/cna/assets/null.py +2 -5
  31. reconcile/cna/integration.py +2 -3
  32. reconcile/cna/state.py +2 -5
  33. reconcile/dashdotdb_base.py +8 -11
  34. reconcile/dashdotdb_cso.py +3 -6
  35. reconcile/dashdotdb_dora.py +10 -14
  36. reconcile/dashdotdb_dvo.py +10 -13
  37. reconcile/dashdotdb_slo.py +5 -8
  38. reconcile/database_access_manager.py +5 -6
  39. reconcile/dynatrace_token_provider/integration.py +2 -5
  40. reconcile/external_resources/integration.py +1 -1
  41. reconcile/external_resources/manager.py +4 -4
  42. reconcile/external_resources/model.py +3 -3
  43. reconcile/external_resources/secrets_sync.py +5 -5
  44. reconcile/external_resources/state.py +5 -5
  45. reconcile/gabi_authorized_users.py +3 -6
  46. reconcile/gcr_mirror.py +1 -1
  47. reconcile/github_org.py +1 -3
  48. reconcile/github_repo_invites.py +2 -5
  49. reconcile/gitlab_housekeeping.py +7 -11
  50. reconcile/gitlab_labeler.py +1 -2
  51. reconcile/gitlab_members.py +2 -5
  52. reconcile/gitlab_permissions.py +1 -3
  53. reconcile/glitchtip/integration.py +2 -5
  54. reconcile/glitchtip_project_alerts/integration.py +3 -6
  55. reconcile/glitchtip_project_dsn/integration.py +4 -7
  56. reconcile/integrations_manager.py +5 -8
  57. reconcile/jenkins/types.py +5 -6
  58. reconcile/jenkins_job_builder.py +9 -12
  59. reconcile/jenkins_roles.py +1 -1
  60. reconcile/jira_watcher.py +2 -2
  61. reconcile/ldap_groups/integration.py +2 -5
  62. reconcile/ocm/types.py +21 -26
  63. reconcile/ocm_addons_upgrade_tests_trigger.py +3 -6
  64. reconcile/ocm_clusters.py +8 -8
  65. reconcile/ocm_internal_notifications/integration.py +1 -2
  66. reconcile/ocm_labels/integration.py +2 -5
  67. reconcile/ocm_machine_pools.py +11 -15
  68. reconcile/ocm_upgrade_scheduler_org_updater.py +2 -5
  69. reconcile/openshift_base.py +27 -29
  70. reconcile/openshift_groups.py +15 -20
  71. reconcile/openshift_namespace_labels.py +8 -14
  72. reconcile/openshift_namespaces.py +5 -8
  73. reconcile/openshift_network_policies.py +2 -4
  74. reconcile/openshift_resources_base.py +19 -29
  75. reconcile/openshift_saas_deploy.py +9 -10
  76. reconcile/openshift_saas_deploy_change_tester.py +7 -10
  77. reconcile/openshift_saas_deploy_trigger_base.py +4 -7
  78. reconcile/openshift_saas_deploy_trigger_cleaner.py +5 -8
  79. reconcile/openshift_saas_deploy_trigger_configs.py +1 -2
  80. reconcile/openshift_saas_deploy_trigger_images.py +1 -2
  81. reconcile/openshift_saas_deploy_trigger_moving_commits.py +1 -2
  82. reconcile/openshift_saas_deploy_trigger_upstream_jobs.py +1 -2
  83. reconcile/openshift_tekton_resources.py +7 -11
  84. reconcile/openshift_upgrade_watcher.py +10 -13
  85. reconcile/openshift_users.py +8 -11
  86. reconcile/oum/base.py +3 -4
  87. reconcile/oum/labelset.py +1 -2
  88. reconcile/oum/metrics.py +2 -2
  89. reconcile/oum/models.py +1 -2
  90. reconcile/oum/standalone.py +2 -3
  91. reconcile/prometheus_rules_tester/integration.py +6 -9
  92. reconcile/quay_membership.py +1 -2
  93. reconcile/quay_mirror.py +12 -13
  94. reconcile/quay_mirror_org.py +10 -10
  95. reconcile/queries.py +4 -7
  96. reconcile/resource_scraper.py +3 -4
  97. reconcile/rhidp/common.py +2 -2
  98. reconcile/saas_auto_promotions_manager/integration.py +5 -6
  99. reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py +1 -2
  100. reconcile/saas_auto_promotions_manager/publisher.py +5 -6
  101. reconcile/saas_auto_promotions_manager/subscriber.py +3 -4
  102. reconcile/saas_file_validator.py +2 -5
  103. reconcile/signalfx_endpoint_monitoring.py +2 -5
  104. reconcile/skupper_network/integration.py +3 -6
  105. reconcile/skupper_network/models.py +3 -5
  106. reconcile/slack_base.py +4 -7
  107. reconcile/slack_usergroups.py +15 -17
  108. reconcile/sql_query.py +5 -9
  109. reconcile/status_board.py +4 -5
  110. reconcile/statuspage/atlassian.py +14 -15
  111. reconcile/statuspage/integrations/maintenances.py +3 -3
  112. reconcile/statuspage/page.py +8 -8
  113. reconcile/statuspage/state.py +4 -5
  114. reconcile/statuspage/status.py +7 -8
  115. reconcile/templating/lib/rendering.py +8 -8
  116. reconcile/templating/renderer.py +10 -11
  117. reconcile/templating/validator.py +4 -4
  118. reconcile/terraform_aws_route53.py +3 -6
  119. reconcile/terraform_cloudflare_dns.py +9 -12
  120. reconcile/terraform_cloudflare_resources.py +9 -11
  121. reconcile/terraform_cloudflare_users.py +8 -11
  122. reconcile/terraform_init/integration.py +2 -2
  123. reconcile/terraform_repo.py +11 -14
  124. reconcile/terraform_resources.py +20 -21
  125. reconcile/terraform_tgw_attachments.py +32 -36
  126. reconcile/terraform_users.py +6 -7
  127. reconcile/terraform_vpc_resources/integration.py +5 -5
  128. reconcile/test/conftest.py +7 -10
  129. reconcile/test/fixtures.py +1 -1
  130. reconcile/test/saas_auto_promotions_manager/conftest.py +2 -2
  131. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +2 -2
  132. reconcile/test/test_database_access_manager.py +3 -6
  133. reconcile/test/test_gitlab_labeler.py +2 -5
  134. reconcile/test/test_jump_host.py +5 -8
  135. reconcile/test/test_ocm_machine_pools.py +1 -4
  136. reconcile/test/test_openshift_base.py +3 -6
  137. reconcile/test/test_openshift_cluster_bots.py +5 -5
  138. reconcile/test/test_openshift_namespace_labels.py +2 -3
  139. reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py +2 -2
  140. reconcile/test/test_saasherder.py +9 -12
  141. reconcile/test/test_slack_base.py +4 -6
  142. reconcile/test/test_status_board.py +4 -7
  143. reconcile/test/test_terraform_tgw_attachments.py +14 -20
  144. reconcile/typed_queries/alerting_services_settings.py +1 -2
  145. reconcile/typed_queries/app_interface_custom_messages.py +2 -3
  146. reconcile/typed_queries/app_interface_deadmanssnitch_settings.py +1 -3
  147. reconcile/typed_queries/app_interface_repo_url.py +1 -2
  148. reconcile/typed_queries/app_interface_state_settings.py +1 -3
  149. reconcile/typed_queries/app_interface_vault_settings.py +1 -2
  150. reconcile/typed_queries/aws_vpc_requests.py +1 -3
  151. reconcile/typed_queries/aws_vpcs.py +1 -3
  152. reconcile/typed_queries/clusters.py +2 -4
  153. reconcile/typed_queries/clusters_minimal.py +1 -3
  154. reconcile/typed_queries/clusters_with_dms.py +1 -3
  155. reconcile/typed_queries/external_resources.py +3 -4
  156. reconcile/typed_queries/pagerduty_instances.py +1 -2
  157. reconcile/typed_queries/repos.py +2 -3
  158. reconcile/typed_queries/reserved_networks.py +1 -3
  159. reconcile/typed_queries/saas_files.py +49 -59
  160. reconcile/typed_queries/slo_documents.py +1 -3
  161. reconcile/typed_queries/status_board.py +3 -7
  162. reconcile/typed_queries/tekton_pipeline_providers.py +1 -2
  163. reconcile/typed_queries/terraform_namespaces.py +1 -2
  164. reconcile/typed_queries/terraform_tgw_attachments/aws_accounts.py +1 -3
  165. reconcile/utils/acs/base.py +2 -3
  166. reconcile/utils/acs/notifiers.py +3 -3
  167. reconcile/utils/acs/policies.py +3 -3
  168. reconcile/utils/aggregated_list.py +1 -1
  169. reconcile/utils/amtool.py +1 -2
  170. reconcile/utils/aws_api.py +28 -31
  171. reconcile/utils/binary.py +1 -3
  172. reconcile/utils/clusterhealth/providerbase.py +1 -2
  173. reconcile/utils/clusterhealth/telemeter.py +2 -2
  174. reconcile/utils/deadmanssnitch_api.py +1 -2
  175. reconcile/utils/disabled_integrations.py +4 -6
  176. reconcile/utils/environ.py +1 -1
  177. reconcile/utils/expiration.py +3 -7
  178. reconcile/utils/external_resource_spec.py +3 -4
  179. reconcile/utils/external_resources.py +4 -7
  180. reconcile/utils/filtering.py +1 -2
  181. reconcile/utils/git.py +3 -9
  182. reconcile/utils/git_secrets.py +5 -5
  183. reconcile/utils/github_api.py +5 -9
  184. reconcile/utils/gitlab_api.py +2 -3
  185. reconcile/utils/glitchtip/client.py +2 -4
  186. reconcile/utils/glitchtip/models.py +8 -11
  187. reconcile/utils/gql.py +26 -35
  188. reconcile/utils/grouping.py +1 -3
  189. reconcile/utils/imap_client.py +2 -5
  190. reconcile/utils/internal_groups/client.py +1 -2
  191. reconcile/utils/internal_groups/models.py +8 -9
  192. reconcile/utils/jenkins_api.py +4 -4
  193. reconcile/utils/jinja2/extensions.py +1 -1
  194. reconcile/utils/jinja2/filters.py +4 -4
  195. reconcile/utils/jinja2/utils.py +16 -16
  196. reconcile/utils/jira_client.py +10 -11
  197. reconcile/utils/jjb_client.py +14 -17
  198. reconcile/utils/jobcontroller/controller.py +5 -5
  199. reconcile/utils/jobcontroller/models.py +2 -2
  200. reconcile/utils/jsonpath.py +4 -5
  201. reconcile/utils/jump_host.py +7 -8
  202. reconcile/utils/keycloak.py +3 -7
  203. reconcile/utils/ldap_client.py +2 -3
  204. reconcile/utils/lean_terraform_client.py +13 -17
  205. reconcile/utils/membershipsources/app_interface_resolver.py +1 -1
  206. reconcile/utils/membershipsources/models.py +19 -22
  207. reconcile/utils/metrics.py +13 -15
  208. reconcile/utils/mr/base.py +7 -11
  209. reconcile/utils/mr/glitchtip_access_reporter.py +2 -2
  210. reconcile/utils/mr/notificator.py +1 -2
  211. reconcile/utils/oc.py +32 -38
  212. reconcile/utils/oc_connection_parameters.py +24 -25
  213. reconcile/utils/oc_filters.py +2 -3
  214. reconcile/utils/oc_map.py +9 -15
  215. reconcile/utils/ocm/addons.py +7 -10
  216. reconcile/utils/ocm/base.py +38 -39
  217. reconcile/utils/ocm/clusters.py +6 -9
  218. reconcile/utils/ocm/label_sources.py +1 -2
  219. reconcile/utils/ocm/labels.py +3 -6
  220. reconcile/utils/ocm/ocm.py +11 -14
  221. reconcile/utils/ocm/products.py +1 -3
  222. reconcile/utils/ocm/search_filters.py +16 -17
  223. reconcile/utils/ocm/service_log.py +2 -3
  224. reconcile/utils/ocm/sre_capability_labels.py +4 -8
  225. reconcile/utils/ocm/subscriptions.py +1 -3
  226. reconcile/utils/ocm/syncsets.py +2 -4
  227. reconcile/utils/ocm/upgrades.py +5 -9
  228. reconcile/utils/ocm_base_client.py +13 -16
  229. reconcile/utils/openshift_resource.py +5 -11
  230. reconcile/utils/output.py +2 -3
  231. reconcile/utils/pagerduty_api.py +4 -5
  232. reconcile/utils/prometheus.py +2 -2
  233. reconcile/utils/promotion_state.py +4 -5
  234. reconcile/utils/promtool.py +2 -8
  235. reconcile/utils/quay_api.py +12 -22
  236. reconcile/utils/raw_github_api.py +3 -5
  237. reconcile/utils/rosa/rosa_cli.py +6 -6
  238. reconcile/utils/rosa/session.py +6 -7
  239. reconcile/utils/runtime/desired_state_diff.py +3 -8
  240. reconcile/utils/runtime/environment.py +4 -7
  241. reconcile/utils/runtime/integration.py +4 -4
  242. reconcile/utils/runtime/meta.py +1 -2
  243. reconcile/utils/runtime/runner.py +7 -10
  244. reconcile/utils/runtime/sharding.py +22 -27
  245. reconcile/utils/saasherder/interfaces.py +63 -69
  246. reconcile/utils/saasherder/models.py +30 -35
  247. reconcile/utils/saasherder/saasherder.py +37 -53
  248. reconcile/utils/secret_reader.py +17 -19
  249. reconcile/utils/slack_api.py +15 -17
  250. reconcile/utils/smtp_client.py +1 -2
  251. reconcile/utils/sqs_gateway.py +1 -3
  252. reconcile/utils/state.py +1 -2
  253. reconcile/utils/terraform/config_client.py +4 -5
  254. reconcile/utils/terraform_client.py +3 -8
  255. reconcile/utils/terrascript/cloudflare_client.py +4 -10
  256. reconcile/utils/terrascript/cloudflare_resources.py +10 -13
  257. reconcile/utils/terrascript/models.py +2 -3
  258. reconcile/utils/terrascript/resources.py +1 -2
  259. reconcile/utils/terrascript_aws_client.py +30 -38
  260. reconcile/utils/unleash/client.py +4 -7
  261. reconcile/utils/unleash/server.py +2 -2
  262. reconcile/utils/vault.py +8 -11
  263. reconcile/utils/vaultsecretref.py +2 -3
  264. reconcile/utils/vcs.py +7 -8
  265. reconcile/vault_replication.py +4 -8
  266. reconcile/vpc_peerings_validator.py +4 -9
  267. release/version.py +6 -7
  268. tools/app_interface_reporter.py +2 -2
  269. tools/cli_commands/gpg_encrypt.py +3 -6
  270. tools/cli_commands/systems_and_tools.py +4 -7
  271. tools/qontract_cli.py +31 -17
  272. tools/saas_promotion_state/__init__.py +0 -0
  273. tools/saas_promotion_state/saas_promotion_state.py +72 -0
  274. tools/template_validation.py +1 -1
  275. tools/test/conftest.py +45 -6
  276. tools/test/test_saas_promotion_state.py +86 -0
  277. {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/WHEEL +0 -0
  278. {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/entry_points.txt +0 -0
  279. {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/top_level.txt +0 -0
@@ -21,7 +21,6 @@ from json import JSONDecodeError
21
21
  from threading import Lock
22
22
  from typing import (
23
23
  Any,
24
- Optional,
25
24
  cast,
26
25
  )
27
26
 
@@ -379,9 +378,9 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
379
378
  integration_prefix: str,
380
379
  thread_pool_size: int,
381
380
  accounts: Iterable[dict[str, Any]],
382
- settings: Optional[Mapping[str, Any]] = None,
383
- prefetch_resources_by_schemas: Optional[list[str]] = None,
384
- secret_reader: Optional[SecretReaderBase] = None,
381
+ settings: Mapping[str, Any] | None = None,
382
+ prefetch_resources_by_schemas: list[str] | None = None,
383
+ secret_reader: SecretReaderBase | None = None,
385
384
  ) -> None:
386
385
  self.integration = integration
387
386
  self.integration_prefix = integration_prefix
@@ -478,9 +477,9 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
478
477
  self.rosa_authenticator_pre_signup_zip_lock = Lock()
479
478
  self.lambda_zip: dict[str, str] = {}
480
479
  self.lambda_lock = Lock()
481
- self.github: Optional[Github] = None
480
+ self.github: Github | None = None
482
481
  self.github_lock = Lock()
483
- self.gitlab: Optional[GitLabApi] = None
482
+ self.gitlab: GitLabApi | None = None
484
483
  self.gitlab_lock = Lock()
485
484
  self.jenkins_map: dict[str, JenkinsApi] = {}
486
485
  self.jenkins_lock = Lock()
@@ -509,7 +508,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
509
508
 
510
509
  # defaults from account
511
510
  bucket_backend_value = config.get("bucket")
512
- key_backend_value = config.get("{}_key".format(integration))
511
+ key_backend_value = config.get(f"{integration}_key")
513
512
  region_backend_value = config.get("region")
514
513
  terraform_state = config["terraformState"]
515
514
  if terraform_state:
@@ -757,7 +756,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
757
756
  self,
758
757
  roles,
759
758
  skip_reencrypt_accounts: list[str],
760
- appsre_pgp_key: Optional[str],
759
+ appsre_pgp_key: str | None,
761
760
  ):
762
761
  error = False
763
762
  for role in roles:
@@ -785,9 +784,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
785
784
 
786
785
  # we want to include the console url in the outputs
787
786
  # to be used later to generate the email invitations
788
- output_name = "{}_console-urls__{}".format(
789
- self.integration_prefix, account_name
790
- )
787
+ output_name = f"{self.integration_prefix}_console-urls__{account_name}"
791
788
  output_value = account_console_url
792
789
  tf_output = Output(output_name, value=output_value)
793
790
  self.add_resource(account_name, tf_output)
@@ -846,8 +843,8 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
846
843
  # we want the outputs to be formed into a mail invitation
847
844
  # for each new user. we form an output of the form
848
845
  # 'qrtf.enc-passwords[user_name] = <encrypted password>
849
- output_name = "{}_enc-passwords__{}".format(
850
- self.integration_prefix, user_name
846
+ output_name = (
847
+ f"{self.integration_prefix}_enc-passwords__{user_name}"
851
848
  )
852
849
  output_value = (
853
850
  "${" + tf_iam_user_login_profile.encrypted_password + "}"
@@ -891,7 +888,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
891
888
  self,
892
889
  roles,
893
890
  skip_reencrypt_accounts: list[str],
894
- appsre_pgp_key: Optional[str] = None,
891
+ appsre_pgp_key: str | None = None,
895
892
  ):
896
893
  self.populate_iam_groups(roles)
897
894
  err = self.populate_iam_users(
@@ -912,7 +909,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
912
909
  @staticmethod
913
910
  def get_resource_lifecycle(
914
911
  common_values: dict[str, Any],
915
- ) -> Optional[dict[str, Any]]:
912
+ ) -> dict[str, Any] | None:
916
913
  if lifecycle := common_values.get("lifecycle"):
917
914
  lifecycle = NamespaceTerraformResourceLifecycleV1(**lifecycle)
918
915
  if lifecycle.create_before_destroy is None:
@@ -1013,7 +1010,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
1013
1010
  record["health_check_id"] = f"${{{healthcheck_resource.id}}}"
1014
1011
 
1015
1012
  # Get value from Vault if _records_from_vault was set
1016
- records_from_vault: Optional[Iterable[dict[str, str]]] = record.pop(
1013
+ records_from_vault: Iterable[dict[str, str]] | None = record.pop(
1017
1014
  "records_from_vault", None
1018
1015
  )
1019
1016
  if records_from_vault:
@@ -1467,7 +1464,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
1467
1464
 
1468
1465
  return results
1469
1466
 
1470
- def populate_resources(self, ocm_map: Optional[OCMMap] = None) -> None:
1467
+ def populate_resources(self, ocm_map: OCMMap | None = None) -> None:
1471
1468
  """
1472
1469
  Populates the terraform configuration from resource specs.
1473
1470
  :param ocm_map:
@@ -1479,7 +1476,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
1479
1476
  def init_populate_specs(
1480
1477
  self,
1481
1478
  namespaces: Iterable[Mapping[str, Any]],
1482
- account_names: Optional[Iterable[str]],
1479
+ account_names: Iterable[str] | None,
1483
1480
  ) -> None:
1484
1481
  """
1485
1482
  Initiates resource specs from the definitions in app-interface
@@ -1908,7 +1905,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
1908
1905
 
1909
1906
  def _find_resource_spec(
1910
1907
  self, account: str, source: str, provider: str
1911
- ) -> Optional[ExternalResourceSpec]:
1908
+ ) -> ExternalResourceSpec | None:
1912
1909
  if account not in self.account_resource_specs:
1913
1910
  return None
1914
1911
 
@@ -2168,7 +2165,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
2168
2165
  tf_resources.append(Output(output_name, value=output_value))
2169
2166
  output_name = output_prefix + "__aws_region"
2170
2167
  tf_resources.append(Output(output_name, value=region))
2171
- endpoint = "s3.{}.amazonaws.com".format(region)
2168
+ endpoint = f"s3.{region}.amazonaws.com"
2172
2169
  output_name = output_prefix + "__endpoint"
2173
2170
  tf_resources.append(Output(output_name, value=endpoint))
2174
2171
 
@@ -2480,7 +2477,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
2480
2477
  for k, v in data.items():
2481
2478
  to_replace = "${" + k + "}"
2482
2479
  user_policy = user_policy.replace(to_replace, v)
2483
- output_name = output_prefix + "__{}".format(k)
2480
+ output_name = output_prefix + f"__{k}"
2484
2481
  tf_resources.append(Output(output_name, value=v))
2485
2482
 
2486
2483
  tf_aws_iam_policy = aws_iam_policy(
@@ -2769,10 +2766,8 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
2769
2766
  tf_resources.append(queue_tf_resource)
2770
2767
  output_name = output_prefix + "__aws_region"
2771
2768
  tf_resources.append(Output(output_name, value=region))
2772
- output_name = "{}__{}".format(output_prefix, queue_key)
2773
- output_value = "https://sqs.{}.amazonaws.com/{}/{}".format(
2774
- region, uid, queue_name
2775
- )
2769
+ output_name = f"{output_prefix}__{queue_key}"
2770
+ output_value = f"https://sqs.{region}.amazonaws.com/{uid}/{queue_name}"
2776
2771
  tf_resources.append(Output(output_name, value=output_value))
2777
2772
  all_queues_per_spec.append(all_queues)
2778
2773
 
@@ -2925,7 +2920,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
2925
2920
  values["provider"] = "aws." + region
2926
2921
  table_tf_resource = aws_dynamodb_table(table, **values)
2927
2922
  tf_resources.append(table_tf_resource)
2928
- output_name = "{}__{}".format(output_prefix, table_key)
2923
+ output_name = f"{output_prefix}__{table_key}"
2929
2924
  tf_resources.append(Output(output_name, value=table))
2930
2925
 
2931
2926
  output_name = output_prefix + "__aws_region"
@@ -2960,8 +2955,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
2960
2955
  "Effect": "Allow",
2961
2956
  "Action": ["dynamodb:*"],
2962
2957
  "Resource": [
2963
- "arn:aws:dynamodb:{}:{}:table/{}".format(region, uid, t)
2964
- for t in all_tables
2958
+ f"arn:aws:dynamodb:{region}:{uid}:table/{t}" for t in all_tables
2965
2959
  ],
2966
2960
  }
2967
2961
  ],
@@ -3420,10 +3414,8 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
3420
3414
  tf_resources.append(user_policy_attachment_tf_resource)
3421
3415
 
3422
3416
  # outputs
3423
- output_name = "{}__{}".format(output_prefix, sqs_identifier)
3424
- output_value = "https://sqs.{}.amazonaws.com/{}/{}".format(
3425
- region, uid, sqs_identifier
3426
- )
3417
+ output_name = f"{output_prefix}__{sqs_identifier}"
3418
+ output_value = f"https://sqs.{region}.amazonaws.com/{uid}/{sqs_identifier}"
3427
3419
  tf_resources.append(Output(output_name, value=output_value))
3428
3420
 
3429
3421
  self.add_resources(account, tf_resources)
@@ -4042,8 +4034,8 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
4042
4034
  def add_resource(self, account, tf_resource):
4043
4035
  if account not in self.locks:
4044
4036
  logging.debug(
4045
- "integration {} is disabled for account {}. "
4046
- "can not add resource".format(self.integration, account)
4037
+ f"integration {self.integration} is disabled for account {account}. "
4038
+ "can not add resource"
4047
4039
  )
4048
4040
  return
4049
4041
  with self.locks[account]:
@@ -4051,8 +4043,8 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
4051
4043
 
4052
4044
  def dump(
4053
4045
  self,
4054
- print_to_file: Optional[str] = None,
4055
- existing_dirs: Optional[dict[str, str]] = None,
4046
+ print_to_file: str | None = None,
4047
+ existing_dirs: dict[str, str] | None = None,
4056
4048
  ) -> dict[str, str]:
4057
4049
  """
4058
4050
  Dump the Terraform configurations (in JSON format) to the working directories.
@@ -4311,7 +4303,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
4311
4303
 
4312
4304
  def _get_elasticsearch_account_wide_resource_policy(
4313
4305
  self, account: str
4314
- ) -> Optional[aws_cloudwatch_log_resource_policy]:
4306
+ ) -> aws_cloudwatch_log_resource_policy | None:
4315
4307
  """
4316
4308
  https://docs.aws.amazon.com/opensearch-service/latest/developerguide/createdomain-configure-slow-logs.html
4317
4309
  CloudWatch Logs supports 10 resource policies per Region.
@@ -5386,7 +5378,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
5386
5378
 
5387
5379
  def get_asg_image_id(
5388
5380
  self, filters: Iterable[Mapping[str, Any]], account: str, region: str
5389
- ) -> Optional[str]:
5381
+ ) -> str | None:
5390
5382
  """
5391
5383
  AMI ID comes form AWS Api filter result.
5392
5384
  AMI needs to be shared by integration aws-ami-share.
@@ -2,10 +2,7 @@ import logging
2
2
  import os
3
3
  import threading
4
4
  from collections.abc import Mapping
5
- from typing import (
6
- Any,
7
- Optional,
8
- )
5
+ from typing import Any
9
6
 
10
7
  from UnleashClient import (
11
8
  BaseCache,
@@ -13,7 +10,7 @@ from UnleashClient import (
13
10
  )
14
11
  from UnleashClient.strategies import Strategy
15
12
 
16
- client: Optional[UnleashClient] = None
13
+ client: UnleashClient | None = None
17
14
  client_lock = threading.Lock()
18
15
 
19
16
 
@@ -43,7 +40,7 @@ class ClusterStrategy(Strategy):
43
40
 
44
41
 
45
42
  class DisableClusterStrategy(ClusterStrategy):
46
- def apply(self, context: Optional[dict] = None) -> bool:
43
+ def apply(self, context: dict | None = None) -> bool:
47
44
  enable = True
48
45
 
49
46
  if context and "cluster_name" in context.keys():
@@ -54,7 +51,7 @@ class DisableClusterStrategy(ClusterStrategy):
54
51
 
55
52
 
56
53
  class EnableClusterStrategy(ClusterStrategy):
57
- def apply(self, context: Optional[dict] = None) -> bool:
54
+ def apply(self, context: dict | None = None) -> bool:
58
55
  enable = False
59
56
 
60
57
  if context and "cluster_name" in context.keys():
@@ -1,4 +1,4 @@
1
- from enum import Enum
1
+ from enum import StrEnum
2
2
 
3
3
  import requests
4
4
  from pydantic import BaseModel, Field
@@ -6,7 +6,7 @@ from pydantic import BaseModel, Field
6
6
  from reconcile.utils.rest_api_base import ApiBase, BearerTokenAuth
7
7
 
8
8
 
9
- class FeatureToggleType(str, Enum):
9
+ class FeatureToggleType(StrEnum):
10
10
  experiment = "experiment"
11
11
  kill_switch = "kill-switch"
12
12
  release = "release"
reconcile/utils/vault.py CHANGED
@@ -5,7 +5,6 @@ import threading
5
5
  import time
6
6
  from collections.abc import Mapping
7
7
  from functools import lru_cache
8
- from typing import Optional
9
8
 
10
9
  import hvac
11
10
  import requests
@@ -60,11 +59,11 @@ class _VaultClient:
60
59
 
61
60
  def __init__(
62
61
  self,
63
- server: Optional[str] = None,
64
- role_id: Optional[str] = None,
65
- secret_id: Optional[str] = None,
66
- kube_auth_role: Optional[str] = None,
67
- kube_auth_mount: Optional[str] = None,
62
+ server: str | None = None,
63
+ role_id: str | None = None,
64
+ secret_id: str | None = None,
65
+ kube_auth_role: str | None = None,
66
+ kube_auth_mount: str | None = None,
68
67
  auto_refresh: bool = True,
69
68
  ):
70
69
  config = get_config()
@@ -164,7 +163,7 @@ class _VaultClient:
164
163
  self._client.auth_approle(self.role_id, self.secret_id)
165
164
 
166
165
  @retry()
167
- def read_all_with_version(self, secret: Mapping) -> tuple[Mapping, Optional[str]]:
166
+ def read_all_with_version(self, secret: Mapping) -> tuple[Mapping, str | None]:
168
167
  """Returns a dictionary of keys and values in a Vault secret and the
169
168
  version of the secret, for V1 secrets, version will be None.
170
169
 
@@ -215,9 +214,7 @@ class _VaultClient:
215
214
 
216
215
  return version
217
216
 
218
- def __read_all_v2(
219
- self, path: str, version: Optional[str]
220
- ) -> tuple[dict, Optional[str]]:
217
+ def __read_all_v2(self, path: str, version: str | None) -> tuple[dict, str | None]:
221
218
  path_split = path.split("/")
222
219
  mount_point = path_split[0]
223
220
  read_path = "/".join(path_split[1:])
@@ -306,7 +303,7 @@ class _VaultClient:
306
303
  try:
307
304
  secret_field = data[field]
308
305
  except KeyError:
309
- raise SecretFieldNotFound("{}/{}".format(path, field))
306
+ raise SecretFieldNotFound(f"{path}/{field}")
310
307
  return secret_field
311
308
 
312
309
  @retry()
@@ -1,6 +1,5 @@
1
1
  from dataclasses import dataclass
2
2
  from typing import (
3
- Optional,
4
3
  cast,
5
4
  )
6
5
 
@@ -16,8 +15,8 @@ class VaultSecretRef:
16
15
 
17
16
  path: str
18
17
  field: str
19
- format: Optional[str] = None
20
- version: Optional[int] = None
18
+ format: str | None = None
19
+ version: int | None = None
21
20
 
22
21
  def get(self, field=None, default=None):
23
22
  secret_content = self._resolve_secret()
reconcile/utils/vcs.py CHANGED
@@ -6,7 +6,6 @@ from collections.abc import Iterable
6
6
  from dataclasses import dataclass
7
7
  from datetime import datetime
8
8
  from enum import Enum
9
- from typing import Optional
10
9
 
11
10
  from gitlab.v4.objects import ProjectMergeRequest
12
11
 
@@ -57,10 +56,10 @@ class VCS:
57
56
  dry_run: bool,
58
57
  allow_deleting_mrs: bool = False,
59
58
  allow_opening_mrs: bool = False,
60
- gitlab_instance: Optional[GitLabApi] = None,
61
- default_gh_token: Optional[str] = None,
62
- app_interface_api: Optional[GitLabApi] = None,
63
- github_api_per_repo_url: Optional[dict[str, GithubRepositoryApi]] = None,
59
+ gitlab_instance: GitLabApi | None = None,
60
+ default_gh_token: str | None = None,
61
+ app_interface_api: GitLabApi | None = None,
62
+ github_api_per_repo_url: dict[str, GithubRepositoryApi] | None = None,
64
63
  ):
65
64
  self._dry_run = dry_run
66
65
  self._allow_deleting_mrs = allow_deleting_mrs
@@ -106,7 +105,7 @@ class VCS:
106
105
  return defaults[0]
107
106
 
108
107
  def _init_github(
109
- self, repo_url: str, auth_code: Optional[HasSecret]
108
+ self, repo_url: str, auth_code: HasSecret | None
110
109
  ) -> GithubRepositoryApi:
111
110
  if repo_url not in self._gh_per_repo_url:
112
111
  if auth_code:
@@ -159,7 +158,7 @@ class VCS:
159
158
  return MRCheckStatus.NONE
160
159
 
161
160
  def get_commit_sha(
162
- self, repo_url: str, ref: str, auth_code: Optional[HasSecret]
161
+ self, repo_url: str, ref: str, auth_code: HasSecret | None
163
162
  ) -> str:
164
163
  if bool(self._is_commit_sha_regex.search(ref)):
165
164
  return ref
@@ -174,7 +173,7 @@ class VCS:
174
173
  repo_url: str,
175
174
  commit_from: str,
176
175
  commit_to: str,
177
- auth_code: Optional[HasSecret],
176
+ auth_code: HasSecret | None,
178
177
  ) -> list[Commit]:
179
178
  """
180
179
  Return a list of commits between two commits.
@@ -2,8 +2,6 @@ import logging
2
2
  import re
3
3
  from collections.abc import Iterable
4
4
  from typing import (
5
- Optional,
6
- Union,
7
5
  cast,
8
6
  )
9
7
 
@@ -179,7 +177,7 @@ def copy_vault_secret(
179
177
 
180
178
  def check_invalid_paths(
181
179
  path_list: Iterable[str],
182
- policy_paths: Optional[Iterable[str]],
180
+ policy_paths: Iterable[str] | None,
183
181
  ) -> None:
184
182
  """Checks if the paths to be replicated are present in the policy used to limit the secrets
185
183
  that are going to be replicated."""
@@ -283,12 +281,10 @@ def get_jenkins_secret_list(
283
281
 
284
282
 
285
283
  def get_vault_credentials(
286
- vault_auth: Union[
287
- VaultReplicationConfigV1_VaultInstanceAuthV1,
288
- VaultInstanceV1_VaultReplicationConfigV1_VaultInstanceAuthV1,
289
- ],
284
+ vault_auth: VaultReplicationConfigV1_VaultInstanceAuthV1
285
+ | VaultInstanceV1_VaultReplicationConfigV1_VaultInstanceAuthV1,
290
286
  vault_address: str,
291
- ) -> dict[str, Optional[str]]:
287
+ ) -> dict[str, str | None]:
292
288
  """Returns a dictionary with the credentials used to authenticate with Vault,
293
289
  retrieved from the values present on AppInterface and comming from Vault itself."""
294
290
  vault_creds = {}
@@ -2,7 +2,6 @@ import ipaddress
2
2
  import logging
3
3
  import sys
4
4
  from typing import (
5
- Union,
6
5
  cast,
7
6
  )
8
7
 
@@ -107,10 +106,8 @@ def validate_no_internal_to_public_peerings(
107
106
  }:
108
107
  continue
109
108
  connection = cast(
110
- Union[
111
- ClusterPeeringConnectionClusterAccepterV1,
112
- ClusterPeeringConnectionClusterRequesterV1,
113
- ],
109
+ ClusterPeeringConnectionClusterAccepterV1
110
+ | ClusterPeeringConnectionClusterRequesterV1,
114
111
  connection,
115
112
  )
116
113
  peer = connection.cluster
@@ -150,10 +147,8 @@ def validate_no_public_to_public_peerings(
150
147
  }:
151
148
  continue
152
149
  connection = cast(
153
- Union[
154
- ClusterPeeringConnectionClusterAccepterV1,
155
- ClusterPeeringConnectionClusterRequesterV1,
156
- ],
150
+ ClusterPeeringConnectionClusterAccepterV1
151
+ | ClusterPeeringConnectionClusterRequesterV1,
157
152
  connection,
158
153
  )
159
154
  peer = connection.cluster
release/version.py CHANGED
@@ -5,7 +5,6 @@ import os
5
5
  import re
6
6
  import subprocess
7
7
  import sys
8
- from subprocess import PIPE
9
8
  from typing import Optional
10
9
 
11
10
  GIT_VERSION_FILE = "GIT_VERSION"
@@ -21,7 +20,7 @@ def git() -> str:
21
20
  """
22
21
  cmd = "git describe --tags --match=[0-9]*.[0-9]*.[0-9]*"
23
22
  try:
24
- p = subprocess.run(cmd.split(" "), stdout=PIPE, stderr=PIPE, check=True)
23
+ p = subprocess.run(cmd.split(" "), capture_output=True, check=True)
25
24
  v = p.stdout.decode("utf-8").strip()
26
25
  # tox is running setup.py sdist from the git repo, and then runs again outside
27
26
  # of the git repo. At this second step, we cannot run git commands.
@@ -35,7 +34,7 @@ def git() -> str:
35
34
  # if we're not in a git repo, try reading out from the GIT_VERSION file
36
35
  if os.path.exists(GIT_VERSION_FILE):
37
36
  with open(
38
- GIT_VERSION_FILE, "r", encoding=locale.getpreferredencoding(False)
37
+ GIT_VERSION_FILE, encoding=locale.getpreferredencoding(False)
39
38
  ) as f:
40
39
  return f.read()
41
40
  print(e.stderr)
@@ -45,11 +44,11 @@ def git() -> str:
45
44
  def commit(length: int = 7) -> str:
46
45
  """get the current git commitid"""
47
46
  cmd = f"git rev-parse --short={length} HEAD"
48
- p = subprocess.run(cmd.split(" "), stdout=PIPE, stderr=PIPE, check=True)
47
+ p = subprocess.run(cmd.split(" "), capture_output=True, check=True)
49
48
  return p.stdout.decode("utf-8").strip()
50
49
 
51
50
 
52
- def semver(git_version: Optional[str] = None) -> str:
51
+ def semver(git_version: Optional[str] = None) -> str: # noqa: UP007 - RHEL8 has python 3.8
53
52
  """get a semantic version out of the input git version (see git())
54
53
  - if a X.Y.Z tag is set on the current HEAD, we'll use this
55
54
  - else we'll use X.Y.<Z+1>-<count>+<commitid> to respect semver and version
@@ -72,7 +71,7 @@ def semver(git_version: Optional[str] = None) -> str:
72
71
  return str(v)
73
72
 
74
73
 
75
- def pip(git_version: Optional[str] = None) -> str:
74
+ def pip(git_version: Optional[str] = None) -> str: # noqa: UP007 - RHEL8 has python 3.8
76
75
  """get a pip version out of the input git version (see git()),
77
76
  according to https://peps.python.org/pep-0440/
78
77
  - if a X.Y.Z tag is set on the current HEAD, we'll use this
@@ -88,7 +87,7 @@ def pip(git_version: Optional[str] = None) -> str:
88
87
  # return str(v)
89
88
 
90
89
 
91
- def docker(git_version: Optional[str] = None) -> str:
90
+ def docker(git_version: Optional[str] = None) -> str: # noqa: UP007 - RHEL8 has python 3.8
92
91
  # docker tags don't like '+' characters, let's remove the buildinfo/commitid
93
92
  return pip(git_version)
94
93
 
@@ -2,8 +2,8 @@ import logging
2
2
  import os
3
3
  import textwrap
4
4
  from datetime import (
5
+ UTC,
5
6
  datetime,
6
- timezone,
7
7
  )
8
8
 
9
9
  import click
@@ -221,7 +221,7 @@ def get_apps_data(date, month_delta=1, thread_pool_size=10):
221
221
  jjb: JJB = init_jjb(secret_reader)
222
222
  jenkins_map = jenkins_base.get_jenkins_map()
223
223
  time_limit = date - relativedelta(months=month_delta)
224
- timestamp_limit = int(time_limit.replace(tzinfo=timezone.utc).timestamp())
224
+ timestamp_limit = int(time_limit.replace(tzinfo=UTC).timestamp())
225
225
 
226
226
  secret_content = secret_reader.read_all({"path": DASHDOTDB_SECRET})
227
227
  dashdotdb_url = secret_content["url"]
@@ -1,11 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import json
4
+ from collections.abc import Mapping
4
5
  from dataclasses import dataclass
5
- from typing import (
6
- Mapping,
7
- Optional,
8
- )
9
6
 
10
7
  from reconcile import queries
11
8
  from reconcile.utils import (
@@ -114,7 +111,7 @@ class GPGEncryptCommand:
114
111
  f"No argument given which defines how to fetch the secret {self._command_data}"
115
112
  )
116
113
 
117
- def _get_gpg_key(self) -> Optional[str]:
114
+ def _get_gpg_key(self) -> str | None:
118
115
  target_user = self._command_data.target_user
119
116
  users = queries.get_users_by(
120
117
  refs=False,
@@ -156,7 +153,7 @@ class GPGEncryptCommand:
156
153
  def create(
157
154
  cls,
158
155
  command_data: GPGEncryptCommandData,
159
- secret_reader: Optional[SecretReader] = None,
156
+ secret_reader: SecretReader | None = None,
160
157
  ) -> GPGEncryptCommand:
161
158
  cls_secret_reader = (
162
159
  secret_reader
@@ -3,7 +3,6 @@
3
3
 
4
4
  from typing import (
5
5
  Any,
6
- Optional,
7
6
  Self,
8
7
  )
9
8
 
@@ -145,7 +144,7 @@ class SystemTool(BaseModel):
145
144
 
146
145
  @classmethod
147
146
  def init_from_model(
148
- cls, model: Any, enumeration: Any, parent: Optional[str] = None
147
+ cls, model: Any, enumeration: Any, parent: str | None = None
149
148
  ) -> Self:
150
149
  match model:
151
150
  case GitlabInstanceV1():
@@ -284,7 +283,7 @@ class SystemTool(BaseModel):
284
283
  cls,
285
284
  c: OpenShiftClusterManagerUpgradePolicyClusterV1,
286
285
  enumeration: Any,
287
- parent: Optional[str] = None,
286
+ parent: str | None = None,
288
287
  ) -> Self:
289
288
  return cls(
290
289
  system_type="openshift",
@@ -394,15 +393,13 @@ class SystemToolInventory:
394
393
  def __init__(self) -> None:
395
394
  self.systems_and_tools: list[SystemTool] = []
396
395
 
397
- def append(
398
- self, model: Any, enumeration: Any, parent: Optional[str] = None
399
- ) -> None:
396
+ def append(self, model: Any, enumeration: Any, parent: str | None = None) -> None:
400
397
  self.systems_and_tools.append(
401
398
  SystemTool.init_from_model(model, enumeration, parent=parent)
402
399
  )
403
400
 
404
401
  def update(
405
- self, models: list[Any], enumeration: Any, parent: Optional[str] = None
402
+ self, models: list[Any], enumeration: Any, parent: str | None = None
406
403
  ) -> None:
407
404
  for m in models:
408
405
  self.append(m, enumeration, parent=parent)