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
@@ -16,7 +16,6 @@ from enum import Enum
16
16
  from typing import (
17
17
  Any,
18
18
  Optional,
19
- Tuple,
20
19
  )
21
20
 
22
21
  import jinja2
@@ -59,7 +58,7 @@ class ChangeTypePriority(Enum):
59
58
  LOW = "low"
60
59
 
61
60
 
62
- def parent_of_jsonpath(path: jsonpath_ng.JSONPath) -> Optional[jsonpath_ng.JSONPath]:
61
+ def parent_of_jsonpath(path: jsonpath_ng.JSONPath) -> jsonpath_ng.JSONPath | None:
63
62
  # todo - figure out if this is enough of if we have other
64
63
  # structures where a parent can be extracted
65
64
  if isinstance(path, jsonpath_ng.Child):
@@ -267,8 +266,8 @@ class PathExpression:
267
266
  @dataclass
268
267
  class FileChange:
269
268
  file_ref: FileRef
270
- old: Optional[dict[str, Any]]
271
- new: Optional[dict[str, Any]]
269
+ old: dict[str, Any] | None
270
+ new: dict[str, Any] | None
272
271
  old_backrefs: set[FileRef] = field(default_factory=set)
273
272
  new_backrefs: set[FileRef] = field(default_factory=set)
274
273
 
@@ -277,7 +276,7 @@ class OwnershipContext(ABC):
277
276
  @abstractmethod
278
277
  def find_ownership_context(
279
278
  self,
280
- context_schema: Optional[str],
279
+ context_schema: str | None,
281
280
  change: FileChange,
282
281
  ) -> list[FileRef]: ...
283
282
 
@@ -285,11 +284,11 @@ class OwnershipContext(ABC):
285
284
  @dataclass
286
285
  class ForwardrefOwnershipContext(OwnershipContext):
287
286
  selector: jsonpath_ng.JSONPath
288
- when: Optional[str] = None
287
+ when: str | None = None
289
288
 
290
289
  def find_ownership_context(
291
290
  self,
292
- context_schema: Optional[str],
291
+ context_schema: str | None,
293
292
  change: FileChange,
294
293
  ) -> list[FileRef]:
295
294
  old_contexts = {e.value for e in self.selector.find(change.old)}
@@ -319,11 +318,11 @@ class ForwardrefOwnershipContext(OwnershipContext):
319
318
  class BackrefOwnershipContext(OwnershipContext):
320
319
  selector: jsonpath_ng.JSONPath
321
320
  file_diff_resolver: FileDiffResolver
322
- when: Optional[str] = None
321
+ when: str | None = None
323
322
 
324
323
  def find_ownership_context(
325
324
  self,
326
- context_schema: Optional[str],
325
+ context_schema: str | None,
327
326
  change: FileChange,
328
327
  ) -> list[FileRef]:
329
328
  # get backref datafile content
@@ -369,7 +368,7 @@ class ContextExpansion:
369
368
  def expand_from_file_ref(
370
369
  self,
371
370
  file_ref: FileRef,
372
- expansion_trail: Set[Tuple[str, FileRef]],
371
+ expansion_trail: Set[tuple[str, FileRef]],
373
372
  ) -> list["ResolvedContext"]:
374
373
  old_data, new_data = self.file_diff_resolver.lookup_file_diff(file_ref)
375
374
  return self.expand(
@@ -384,7 +383,7 @@ class ContextExpansion:
384
383
  def expand(
385
384
  self,
386
385
  change: FileChange,
387
- expansion_trail: Set[Tuple[str, FileRef]],
386
+ expansion_trail: Set[tuple[str, FileRef]],
388
387
  ) -> list["ResolvedContext"]:
389
388
  """
390
389
  Find context based on the `self.context`, lookup the file diff for
@@ -395,7 +394,7 @@ class ContextExpansion:
395
394
  context_schema=self.change_type.context_schema,
396
395
  change=change,
397
396
  )
398
- expaned_context_file_refs: list["ResolvedContext"] = []
397
+ expaned_context_file_refs: list[ResolvedContext] = []
399
398
  for ref in context_file_refs:
400
399
  ref_old_data, ref_new_data = self.file_diff_resolver.lookup_file_diff(ref)
401
400
  expaned_context_file_refs.extend(
@@ -429,9 +428,9 @@ class ChangeDetector(ABC):
429
428
  Represents an item from a change-types `change` list.
430
429
  """
431
430
 
432
- context_schema: Optional[str]
433
- change_schema: Optional[str]
434
- context: Optional[OwnershipContext]
431
+ context_schema: str | None
432
+ change_schema: str | None
433
+ context: OwnershipContext | None
435
434
 
436
435
  @abstractmethod
437
436
  def find_context_file_refs(
@@ -478,14 +477,14 @@ class ChangeTypeProcessor:
478
477
  description: str
479
478
  priority: ChangeTypePriority
480
479
  context_type: BundleFileType
481
- context_schema: Optional[str]
480
+ context_schema: str | None
482
481
  disabled: bool
483
482
  implicit_ownership: list[ChangeTypeImplicitOwnershipV1]
484
- restrictive: Optional[bool] = False
483
+ restrictive: bool | None = False
485
484
 
486
485
  def __post_init__(self) -> None:
487
486
  self._expressions_by_file_type_schema: dict[
488
- tuple[BundleFileType, Optional[str]], list[PathExpression]
487
+ tuple[BundleFileType, str | None], list[PathExpression]
489
488
  ] = defaultdict(list)
490
489
  self._change_detectors: list[ChangeDetector] = []
491
490
  self._context_expansions: list[ContextExpansion] = []
@@ -498,7 +497,7 @@ class ChangeTypeProcessor:
498
497
  def find_context_file_refs(
499
498
  self,
500
499
  change: FileChange,
501
- expansion_trail: Set[Tuple[str, FileRef]],
500
+ expansion_trail: Set[tuple[str, FileRef]],
502
501
  ) -> list[ResolvedContext]:
503
502
  """
504
503
  ChangeTypeV1 are attached to bundle files, react to changes within
@@ -638,7 +637,7 @@ class ChangeTypeProcessor:
638
637
  def _allowed_changed_paths_for_file_type_and_schema(
639
638
  self,
640
639
  file_type: BundleFileType,
641
- file_schema: Optional[str],
640
+ file_schema: str | None,
642
641
  file_content: Any,
643
642
  ctx: "ChangeTypeContext",
644
643
  ) -> list[jsonpath_ng.JSONPath]:
@@ -692,8 +691,8 @@ class ChangeTypeProcessor:
692
691
  def build_ownership_context(
693
692
  file_diff_resolver: FileDiffResolver,
694
693
  selector: jsonpath_ng.JSONPath,
695
- when: Optional[str] = None,
696
- where: Optional[str] = None,
694
+ when: str | None = None,
695
+ where: str | None = None,
697
696
  ) -> OwnershipContext:
698
697
  """
699
698
  create an OwnershipContext object based on the provided parameters
@@ -840,8 +839,8 @@ class ChangeTypeContext:
840
839
  origin: str
841
840
  context_file: FileRef
842
841
  approvers: list[Approver]
843
- approver_reachability: Optional[list[ApproverReachability]] = None
844
- change_owner_labels: Optional[set[str]] = None
842
+ approver_reachability: list[ApproverReachability] | None = None
843
+ change_owner_labels: set[str] | None = None
845
844
 
846
845
  @property
847
846
  def disabled(self) -> bool:
@@ -7,10 +7,7 @@ from dataclasses import (
7
7
  dataclass,
8
8
  field,
9
9
  )
10
- from typing import (
11
- Any,
12
- Optional,
13
- )
10
+ from typing import Any
14
11
 
15
12
  import anymarkup
16
13
 
@@ -50,8 +47,8 @@ class BundleFileChange:
50
47
  """
51
48
 
52
49
  fileref: FileRef
53
- old: Optional[dict[str, Any]]
54
- new: Optional[dict[str, Any]]
50
+ old: dict[str, Any] | None
51
+ new: dict[str, Any] | None
55
52
  old_content_sha: str
56
53
  new_content_sha: str
57
54
  diffs: list[Diff]
@@ -81,16 +78,16 @@ class BundleFileChange:
81
78
  return self._diff_coverage[METADATA_CHANGE_PATH]
82
79
 
83
80
  @property
84
- def old_content_with_metadata(self) -> Optional[dict[str, Any]]:
81
+ def old_content_with_metadata(self) -> dict[str, Any] | None:
85
82
  return self._content_with_metadata(self.old)
86
83
 
87
84
  @property
88
- def new_content_with_metadata(self) -> Optional[dict[str, Any]]:
85
+ def new_content_with_metadata(self) -> dict[str, Any] | None:
89
86
  return self._content_with_metadata(self.new)
90
87
 
91
88
  def _content_with_metadata(
92
- self, content: Optional[dict[str, Any]]
93
- ) -> Optional[dict[str, Any]]:
89
+ self, content: dict[str, Any] | None
90
+ ) -> dict[str, Any] | None:
94
91
  if content and self.fileref.file_type == BundleFileType.DATAFILE:
95
92
  content_copy = copy.deepcopy(content)
96
93
  content_copy[DATAFILE_PATH_FIELD_NAME] = self.fileref.path
@@ -219,7 +216,7 @@ class BundleFileChange:
219
216
  return change_types
220
217
 
221
218
 
222
- def parse_resource_file_content(content: Optional[Any]) -> tuple[Any, Optional[str]]:
219
+ def parse_resource_file_content(content: Any | None) -> tuple[Any, str | None]:
223
220
  if content:
224
221
  try:
225
222
  data = anymarkup.parse(content, force_types=None)
@@ -233,7 +230,7 @@ def parse_resource_file_content(content: Optional[Any]) -> tuple[Any, Optional[s
233
230
 
234
231
  def _create_bundle_file_change(
235
232
  path: str,
236
- schema: Optional[str],
233
+ schema: str | None,
237
234
  file_type: BundleFileType,
238
235
  old_file_content: Any,
239
236
  new_file_content: Any,
@@ -241,9 +238,9 @@ def _create_bundle_file_change(
241
238
  new_content_sha: str,
242
239
  old_path: str,
243
240
  new_path: str,
244
- old_backrefs: Optional[list[FileRef]] = None,
245
- new_backrefs: Optional[list[FileRef]] = None,
246
- ) -> Optional[BundleFileChange]:
241
+ old_backrefs: list[FileRef] | None = None,
242
+ new_backrefs: list[FileRef] | None = None,
243
+ ) -> BundleFileChange | None:
247
244
  """
248
245
  this is a factory method that creates a BundleFileChange object based
249
246
  on the old and new content of a file from app-interface. it detects differences
@@ -305,7 +302,7 @@ def _create_bundle_file_change(
305
302
 
306
303
  def get_priority_for_changes(
307
304
  bundle_file_changes: list[BundleFileChange],
308
- ) -> Optional[ChangeTypePriority]:
305
+ ) -> ChangeTypePriority | None:
309
306
  """
310
307
  Finds the lowest priority of all change types involved in the provided bundle file changes.
311
308
  """
@@ -5,10 +5,7 @@ from collections.abc import (
5
5
  )
6
6
  from dataclasses import dataclass
7
7
  from enum import Enum
8
- from typing import (
9
- Any,
10
- Optional,
11
- )
8
+ from typing import Any
12
9
 
13
10
  from reconcile.change_owners.approver import (
14
11
  Approver,
@@ -70,7 +67,7 @@ def get_approver_decisions_from_mr_comments(
70
67
  class ChangeResponsibles:
71
68
  context: str
72
69
  approvers: list[Approver]
73
- approver_reachability: Optional[list[ApproverReachability]] = None
70
+ approver_reachability: list[ApproverReachability] | None = None
74
71
 
75
72
 
76
73
  @dataclass
@@ -3,11 +3,7 @@ import json
3
3
  from dataclasses import dataclass
4
4
  from enum import Enum
5
5
  from functools import reduce
6
- from typing import (
7
- Any,
8
- Optional,
9
- Union,
10
- )
6
+ from typing import Any
11
7
 
12
8
  import jsonpath_ng
13
9
  from deepdiff import DeepDiff
@@ -32,8 +28,8 @@ class Diff:
32
28
 
33
29
  path: jsonpath_ng.JSONPath
34
30
  diff_type: DiffType
35
- old: Optional[Any]
36
- new: Optional[Any]
31
+ old: Any | None
32
+ new: Any | None
37
33
 
38
34
  def create_subdiff(self, sub_path: jsonpath_ng.JSONPath) -> "Diff":
39
35
  if sub_path == self.path:
@@ -60,7 +56,7 @@ class Diff:
60
56
  new=sub_new[0].value if len(sub_new) > 0 else None,
61
57
  )
62
58
 
63
- def get_context_data_copy(self) -> Optional[Any]:
59
+ def get_context_data_copy(self) -> Any | None:
64
60
  if self.diff_type in {DiffType.ADDED, DiffType.CHANGED}:
65
61
  return copy.deepcopy(self.new)
66
62
  if self.diff_type == DiffType.REMOVED:
@@ -70,15 +66,15 @@ class Diff:
70
66
  def path_str(self) -> str:
71
67
  return str(self.path)
72
68
 
73
- def old_value_repr(self) -> Optional[str]:
69
+ def old_value_repr(self) -> str | None:
74
70
  return self._value_repr(self.old)
75
71
 
76
- def new_value_repr(self) -> Optional[str]:
72
+ def new_value_repr(self) -> str | None:
77
73
  return self._value_repr(self.new)
78
74
 
79
- def _value_repr(self, value: Optional[Any]) -> Optional[str]:
75
+ def _value_repr(self, value: Any | None) -> str | None:
80
76
  if value:
81
- if isinstance(value, (dict, list)):
77
+ if isinstance(value, dict | list):
82
78
  return json.dumps(value, indent=2)
83
79
  return str(value)
84
80
  return value
@@ -88,7 +84,7 @@ IDENTIFIER_FIELD_NAME = "__identifier"
88
84
  REF_FIELD_NAME = "$ref"
89
85
 
90
86
 
91
- def _extract_identifier_from_object(obj: Any) -> Optional[str]:
87
+ def _extract_identifier_from_object(obj: Any) -> str | None:
92
88
  if isinstance(obj, dict):
93
89
  if IDENTIFIER_FIELD_NAME in obj:
94
90
  return obj.get(IDENTIFIER_FIELD_NAME)
@@ -98,7 +94,7 @@ def _extract_identifier_from_object(obj: Any) -> Optional[str]:
98
94
 
99
95
 
100
96
  def compare_object_ctx_identifier(
101
- x: Any, y: Any, level: Optional[DiffLevel] = None
97
+ x: Any, y: Any, level: DiffLevel | None = None
102
98
  ) -> bool:
103
99
  """
104
100
  this function helps the deepdiff library to decide if two objects are
@@ -250,7 +246,7 @@ def deepdiff_path_to_jsonpath(deep_diff_path: str) -> jsonpath_ng.JSONPath:
250
246
  if not deep_diff_path.startswith("root"):
251
247
  raise ValueError("a deepdiff path must start with 'root'")
252
248
 
253
- def build_jsonpath_part(element: Union[str, int]) -> jsonpath_ng.JSONPath:
249
+ def build_jsonpath_part(element: str | int) -> jsonpath_ng.JSONPath:
254
250
  match element:
255
251
  case int():
256
252
  return jsonpath_ng.Index(element)
@@ -1,5 +1,4 @@
1
1
  from collections import defaultdict
2
- from typing import Optional
3
2
 
4
3
  from reconcile.change_owners.approver import (
5
4
  ApproverReachability,
@@ -202,7 +201,7 @@ def change_type_contexts_for_self_service_roles(
202
201
  return change_type_contexts
203
202
 
204
203
 
205
- def build_approver(role_member: RoleMember) -> Optional[Approver]:
204
+ def build_approver(role_member: RoleMember) -> Approver | None:
206
205
  """
207
206
  Builds an approver from a role member. Can return None if the passed
208
207
  approver is not considered valid within this context, e.g. not having
@@ -2,10 +2,7 @@ import os
2
2
  import sys
3
3
  from collections.abc import Generator
4
4
  from dataclasses import dataclass
5
- from typing import (
6
- Any,
7
- Optional,
8
- )
5
+ from typing import Any
9
6
 
10
7
  import jsonpath_ng
11
8
  import pygments
@@ -151,7 +148,7 @@ class AppInterfaceRepo:
151
148
  for file in files:
152
149
  if file.endswith(".yml") or file.endswith(".yaml"):
153
150
  filepath = os.path.join(root, file)
154
- with open(filepath, "r", encoding="locale") as f:
151
+ with open(filepath, encoding="locale") as f:
155
152
  parsed_yaml = yaml.safe_load(f)
156
153
  if parsed_yaml.get("$schema") == schema:
157
154
  relative_path = filepath[len(self.data_dir()) :]
@@ -166,7 +163,7 @@ class AppInterfaceRepo:
166
163
  self, file_type: BundleFileType, path: str
167
164
  ) -> BundleFileChange:
168
165
  if file_type == BundleFileType.DATAFILE:
169
- with open(f"{self.data_dir()}{path}", "r", encoding="locale") as f:
166
+ with open(f"{self.data_dir()}{path}", encoding="locale") as f:
170
167
  parsed_yaml = yaml.safe_load(f)
171
168
  return BundleFileChange(
172
169
  fileref=FileRef(
@@ -181,7 +178,7 @@ class AppInterfaceRepo:
181
178
  diffs=[],
182
179
  )
183
180
  elif file_type == BundleFileType.RESOURCEFILE:
184
- with open(f"{self.resource_dir()}{path}", "r", encoding="locale") as f:
181
+ with open(f"{self.resource_dir()}{path}", encoding="locale") as f:
185
182
  content = f.read()
186
183
  parsed_content, schema = parse_resource_file_content(content)
187
184
  return BundleFileChange(
@@ -223,7 +220,7 @@ class FilesystemFileDiffResolver:
223
220
 
224
221
  def lookup_file_diff(
225
222
  self, file_ref: FileRef
226
- ) -> tuple[Optional[dict[str, Any]], Optional[dict[str, Any]]]:
223
+ ) -> tuple[dict[str, Any] | None, dict[str, Any] | None]:
227
224
  file = self.app_interface_repo.bundle_file_for_path(
228
225
  file_type=file_ref.file_type, path=file_ref.path
229
226
  )
@@ -232,7 +229,7 @@ class FilesystemFileDiffResolver:
232
229
 
233
230
  def get_changetype_processor_by_name(
234
231
  change_type_name: str, app_interface_repo: AppInterfaceRepo
235
- ) -> Optional[ChangeTypeProcessor]:
232
+ ) -> ChangeTypeProcessor | None:
236
233
  processors = fetch_change_type_processors(
237
234
  gql.get_api(), FilesystemFileDiffResolver(app_interface_repo)
238
235
  )
@@ -241,7 +238,7 @@ def get_changetype_processor_by_name(
241
238
 
242
239
  def get_self_service_role_by_name(
243
240
  role_name: str,
244
- ) -> Optional[RoleV1]:
241
+ ) -> RoleV1 | None:
245
242
  result = self_service_roles.query(
246
243
  gql.get_api().query, variables={"name": role_name}
247
244
  ).roles
reconcile/checkpoint.py CHANGED
@@ -18,10 +18,7 @@ from functools import (
18
18
  )
19
19
  from http import HTTPStatus
20
20
  from pathlib import Path
21
- from typing import (
22
- Any,
23
- Union,
24
- )
21
+ from typing import Any
25
22
 
26
23
  import requests
27
24
  from jinja2 import Template
@@ -121,7 +118,7 @@ def file_ticket(
121
118
  def report_invalid_metadata(
122
119
  app: Mapping[str, Any],
123
120
  path: str,
124
- board: Mapping[str, Union[str, Mapping]],
121
+ board: Mapping[str, str | Mapping],
125
122
  settings: Mapping[str, Any],
126
123
  parent: str,
127
124
  dry_run: bool = False,
reconcile/cli.py CHANGED
@@ -6,12 +6,9 @@ import os
6
6
  import re
7
7
  import sys
8
8
  import traceback
9
+ from collections.abc import Iterable
9
10
  from signal import SIGUSR1
10
11
  from types import ModuleType
11
- from typing import (
12
- Iterable,
13
- Optional,
14
- )
15
12
 
16
13
  import click
17
14
  import sentry_sdk
@@ -2530,13 +2527,13 @@ def ocm_groups(ctx, thread_pool_size):
2530
2527
  @click.pass_context
2531
2528
  def ocm_clusters(
2532
2529
  ctx,
2533
- gitlab_project_id: Optional[str],
2530
+ gitlab_project_id: str | None,
2534
2531
  thread_pool_size: int,
2535
- job_controller_cluster: Optional[str],
2536
- job_controller_namespace: Optional[str],
2537
- rosa_job_service_account: Optional[str],
2538
- rosa_role: Optional[str],
2539
- rosa_job_image: Optional[str],
2532
+ job_controller_cluster: str | None,
2533
+ job_controller_namespace: str | None,
2534
+ rosa_job_service_account: str | None,
2535
+ rosa_role: str | None,
2536
+ rosa_job_image: str | None,
2540
2537
  ):
2541
2538
  from reconcile.ocm_clusters import (
2542
2539
  OcmClusters,
@@ -2802,7 +2799,7 @@ def version_gate_approver(
2802
2799
  job_controller_namespace: str,
2803
2800
  rosa_job_service_account: str,
2804
2801
  rosa_role: str,
2805
- rosa_job_image: Optional[str],
2802
+ rosa_job_image: str | None,
2806
2803
  ) -> None:
2807
2804
  from reconcile.aus.version_gate_approver import (
2808
2805
  VersionGateApprover,
@@ -3376,7 +3373,7 @@ def signalfx_prometheus_endpoint_monitoring(
3376
3373
  )
3377
3374
 
3378
3375
 
3379
- def parse_image_tag_from_ref(ctx, param, value) -> Optional[dict[str, str]]:
3376
+ def parse_image_tag_from_ref(ctx, param, value) -> dict[str, str] | None:
3380
3377
  if value:
3381
3378
  result = {}
3382
3379
  for v in value:
@@ -3,10 +3,7 @@ import logging
3
3
  from collections import defaultdict
4
4
  from collections.abc import Callable
5
5
  from dataclasses import field
6
- from typing import (
7
- Any,
8
- Optional,
9
- )
6
+ from typing import Any
10
7
  from urllib.parse import urlparse
11
8
 
12
9
  from pydantic.dataclasses import dataclass
@@ -49,14 +46,14 @@ class EndpointMonitoringProvider:
49
46
  name: str
50
47
  provider: str
51
48
  description: str
52
- timeout: Optional[str] = None
53
- checkInterval: Optional[str] = None
54
- blackboxExporter: Optional[BlackboxMonitoringProvider] = None
55
- signalFx: Optional[SignalfxMonitoringProvier] = None
56
- metricLabels: Optional[str] = None
49
+ timeout: str | None = None
50
+ checkInterval: str | None = None
51
+ blackboxExporter: BlackboxMonitoringProvider | None = None
52
+ signalFx: SignalfxMonitoringProvier | None = None
53
+ metricLabels: str | None = None
57
54
 
58
55
  @property
59
- def namespace(self) -> Optional[dict[str, Any]]:
56
+ def namespace(self) -> dict[str, Any] | None:
60
57
  if self.blackboxExporter:
61
58
  return self.blackboxExporter.namespace
62
59
 
@@ -131,7 +128,7 @@ def fill_desired_state(
131
128
  def run_for_provider(
132
129
  provider: str,
133
130
  probe_builder: Callable[
134
- [EndpointMonitoringProvider, list[Endpoint]], Optional[OpenshiftResource]
131
+ [EndpointMonitoringProvider, list[Endpoint]], OpenshiftResource | None
135
132
  ],
136
133
  integration: str,
137
134
  integration_version: str,
@@ -1,9 +1,6 @@
1
1
  import logging
2
2
  import sys
3
- from typing import (
4
- Any,
5
- Optional,
6
- )
3
+ from typing import Any
7
4
 
8
5
  from reconcile.status import ExitCodes
9
6
  from reconcile.typed_queries.app_interface_vault_settings import (
@@ -18,7 +15,7 @@ from reconcile.utils.vault import VaultClient
18
15
  QONTRACT_INTEGRATION = "cluster-deployment-mapper"
19
16
 
20
17
 
21
- def run(dry_run: bool, vault_output_path: Optional[str]) -> None:
18
+ def run(dry_run: bool, vault_output_path: str | None) -> None:
22
19
  """Get Hive ClusterDeployments from clusters and save mapping to Vault"""
23
20
  if not vault_output_path:
24
21
  logging.error("must supply vault output path")
@@ -9,10 +9,7 @@ from dataclasses import (
9
9
  field,
10
10
  )
11
11
  from enum import Enum
12
- from typing import (
13
- Any,
14
- Optional,
15
- )
12
+ from typing import Any
16
13
 
17
14
 
18
15
  class AssetError(Exception):
@@ -31,9 +28,9 @@ class AssetStatus(Enum):
31
28
 
32
29
  @dataclass(frozen=True)
33
30
  class Asset(ABC):
34
- uuid: Optional[str] = field(compare=False, hash=True)
35
- href: Optional[str] = field(compare=False, hash=True)
36
- status: Optional[AssetStatus] = field(compare=False, hash=True)
31
+ uuid: str | None = field(compare=False, hash=True)
32
+ href: str | None = field(compare=False, hash=True)
33
+ status: AssetStatus | None = field(compare=False, hash=True)
37
34
  name: str
38
35
  kind: AssetType
39
36
 
@@ -2,10 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from collections.abc import Mapping
4
4
  from dataclasses import dataclass
5
- from typing import (
6
- Any,
7
- Optional,
8
- )
5
+ from typing import Any
9
6
 
10
7
  from reconcile.cna.assets.asset import (
11
8
  Asset,
@@ -18,7 +15,7 @@ from reconcile.gql_definitions.cna.queries.cna_resources import CNANullAssetV1
18
15
 
19
16
  @dataclass(frozen=True)
20
17
  class NullAsset(Asset):
21
- addr_block: Optional[str]
18
+ addr_block: str | None
22
19
 
23
20
  def api_payload(self) -> dict[str, Any]:
24
21
  return {
@@ -3,7 +3,6 @@ from collections.abc import (
3
3
  Iterable,
4
4
  Mapping,
5
5
  )
6
- from typing import Optional
7
6
 
8
7
  from reconcile.cna.assets.asset_factory import asset_factory_from_schema
9
8
  from reconcile.cna.client import CNAClient
@@ -45,8 +44,8 @@ class CNAIntegration:
45
44
  self,
46
45
  cna_clients: Mapping[str, CNAClient],
47
46
  namespaces: Iterable[NamespaceV1],
48
- desired_states: Optional[Mapping[str, State]] = None,
49
- current_states: Optional[Mapping[str, State]] = None,
47
+ desired_states: Mapping[str, State] | None = None,
48
+ current_states: Mapping[str, State] | None = None,
50
49
  ):
51
50
  self._cna_clients = cna_clients
52
51
  self._namespaces = namespaces
reconcile/cna/state.py CHANGED
@@ -4,10 +4,7 @@ from collections.abc import (
4
4
  Iterable,
5
5
  Mapping,
6
6
  )
7
- from typing import (
8
- Any,
9
- Optional,
10
- )
7
+ from typing import Any
11
8
 
12
9
  from reconcile.cna.assets.asset import (
13
10
  Asset,
@@ -29,7 +26,7 @@ class State:
29
26
  deletions and updates to reach another state.
30
27
  """
31
28
 
32
- def __init__(self, assets: Optional[dict[AssetType, dict[str, Asset]]] = None):
29
+ def __init__(self, assets: dict[AssetType, dict[str, Asset]] | None = None):
33
30
  self._assets: dict[AssetType, dict[str, Asset]] = {}
34
31
  for kind in AssetType:
35
32
  self._assets[kind] = {}