qontract-reconcile 0.10.1rc879__py3-none-any.whl → 0.10.1rc894__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 (291) hide show
  1. {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/METADATA +1 -1
  2. {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/RECORD +291 -284
  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 +9 -14
  13. reconcile/aws_account_manager/reconciler.py +51 -1
  14. reconcile/aws_account_manager/utils.py +3 -0
  15. reconcile/aws_ami_cleanup/integration.py +3 -4
  16. reconcile/aws_iam_password_reset.py +2 -5
  17. reconcile/aws_version_sync/integration.py +2 -2
  18. reconcile/blackbox_exporter_endpoint_monitoring.py +2 -5
  19. reconcile/change_owners/approver.py +4 -5
  20. reconcile/change_owners/bundle.py +20 -22
  21. reconcile/change_owners/change_types.py +23 -24
  22. reconcile/change_owners/changes.py +13 -16
  23. reconcile/change_owners/decision.py +2 -5
  24. reconcile/change_owners/diff.py +11 -15
  25. reconcile/change_owners/self_service_roles.py +1 -2
  26. reconcile/change_owners/tester.py +7 -10
  27. reconcile/checkpoint.py +2 -5
  28. reconcile/cli.py +26 -12
  29. reconcile/closedbox_endpoint_monitoring_base.py +8 -11
  30. reconcile/cluster_deployment_mapper.py +2 -5
  31. reconcile/cna/assets/asset.py +4 -7
  32. reconcile/cna/assets/null.py +2 -5
  33. reconcile/cna/integration.py +2 -3
  34. reconcile/cna/state.py +2 -5
  35. reconcile/dashdotdb_base.py +8 -11
  36. reconcile/dashdotdb_cso.py +3 -6
  37. reconcile/dashdotdb_dora.py +10 -14
  38. reconcile/dashdotdb_dvo.py +10 -13
  39. reconcile/dashdotdb_slo.py +5 -8
  40. reconcile/database_access_manager.py +5 -6
  41. reconcile/dynatrace_token_provider/integration.py +3 -6
  42. reconcile/dynatrace_token_provider/integration_v2.py +20 -0
  43. reconcile/dynatrace_token_provider/meta.py +1 -0
  44. reconcile/external_resources/integration.py +1 -1
  45. reconcile/external_resources/manager.py +4 -4
  46. reconcile/external_resources/model.py +3 -3
  47. reconcile/external_resources/secrets_sync.py +5 -5
  48. reconcile/external_resources/state.py +5 -5
  49. reconcile/gabi_authorized_users.py +3 -6
  50. reconcile/gcr_mirror.py +1 -1
  51. reconcile/github_org.py +1 -3
  52. reconcile/github_repo_invites.py +2 -5
  53. reconcile/gitlab_housekeeping.py +7 -11
  54. reconcile/gitlab_labeler.py +1 -2
  55. reconcile/gitlab_members.py +2 -5
  56. reconcile/gitlab_permissions.py +1 -3
  57. reconcile/glitchtip/integration.py +5 -8
  58. reconcile/glitchtip_project_alerts/integration.py +57 -33
  59. reconcile/glitchtip_project_dsn/integration.py +8 -11
  60. reconcile/gql_definitions/aws_account_manager/aws_accounts.py +6 -0
  61. reconcile/gql_definitions/fragments/aws_account_managed.py +8 -0
  62. reconcile/gql_definitions/glitchtip/glitchtip_project.py +4 -4
  63. reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +27 -7
  64. reconcile/integrations_manager.py +5 -8
  65. reconcile/jenkins/types.py +5 -6
  66. reconcile/jenkins_job_builder.py +9 -12
  67. reconcile/jenkins_roles.py +1 -1
  68. reconcile/jira_watcher.py +2 -2
  69. reconcile/ldap_groups/integration.py +2 -5
  70. reconcile/ocm/types.py +21 -26
  71. reconcile/ocm_addons_upgrade_tests_trigger.py +3 -6
  72. reconcile/ocm_clusters.py +8 -8
  73. reconcile/ocm_internal_notifications/integration.py +1 -2
  74. reconcile/ocm_labels/integration.py +2 -5
  75. reconcile/ocm_machine_pools.py +11 -15
  76. reconcile/ocm_upgrade_scheduler_org_updater.py +2 -5
  77. reconcile/openshift_base.py +29 -30
  78. reconcile/openshift_groups.py +15 -20
  79. reconcile/openshift_namespace_labels.py +8 -14
  80. reconcile/openshift_namespaces.py +5 -8
  81. reconcile/openshift_network_policies.py +2 -4
  82. reconcile/openshift_resources_base.py +19 -29
  83. reconcile/openshift_saas_deploy.py +9 -10
  84. reconcile/openshift_saas_deploy_change_tester.py +7 -10
  85. reconcile/openshift_saas_deploy_trigger_base.py +4 -7
  86. reconcile/openshift_saas_deploy_trigger_cleaner.py +5 -8
  87. reconcile/openshift_saas_deploy_trigger_configs.py +1 -2
  88. reconcile/openshift_saas_deploy_trigger_images.py +1 -2
  89. reconcile/openshift_saas_deploy_trigger_moving_commits.py +1 -2
  90. reconcile/openshift_saas_deploy_trigger_upstream_jobs.py +1 -2
  91. reconcile/openshift_tekton_resources.py +7 -11
  92. reconcile/openshift_upgrade_watcher.py +10 -13
  93. reconcile/openshift_users.py +8 -11
  94. reconcile/oum/base.py +3 -4
  95. reconcile/oum/labelset.py +1 -2
  96. reconcile/oum/metrics.py +2 -2
  97. reconcile/oum/models.py +1 -2
  98. reconcile/oum/standalone.py +2 -3
  99. reconcile/prometheus_rules_tester/integration.py +6 -9
  100. reconcile/quay_membership.py +1 -2
  101. reconcile/quay_mirror.py +12 -13
  102. reconcile/quay_mirror_org.py +10 -10
  103. reconcile/queries.py +4 -7
  104. reconcile/resource_scraper.py +3 -4
  105. reconcile/rhidp/common.py +2 -2
  106. reconcile/saas_auto_promotions_manager/integration.py +5 -6
  107. reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py +1 -2
  108. reconcile/saas_auto_promotions_manager/publisher.py +5 -6
  109. reconcile/saas_auto_promotions_manager/subscriber.py +36 -15
  110. reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +8 -0
  111. reconcile/saas_file_validator.py +2 -5
  112. reconcile/signalfx_endpoint_monitoring.py +2 -5
  113. reconcile/skupper_network/integration.py +3 -6
  114. reconcile/skupper_network/models.py +3 -5
  115. reconcile/slack_base.py +4 -7
  116. reconcile/slack_usergroups.py +15 -17
  117. reconcile/sql_query.py +5 -9
  118. reconcile/status_board.py +4 -5
  119. reconcile/statuspage/atlassian.py +14 -15
  120. reconcile/statuspage/integrations/maintenances.py +3 -3
  121. reconcile/statuspage/page.py +8 -8
  122. reconcile/statuspage/state.py +4 -5
  123. reconcile/statuspage/status.py +7 -8
  124. reconcile/templating/lib/rendering.py +8 -8
  125. reconcile/templating/renderer.py +10 -11
  126. reconcile/templating/validator.py +4 -4
  127. reconcile/terraform_aws_route53.py +3 -6
  128. reconcile/terraform_cloudflare_dns.py +9 -12
  129. reconcile/terraform_cloudflare_resources.py +9 -11
  130. reconcile/terraform_cloudflare_users.py +8 -11
  131. reconcile/terraform_init/integration.py +2 -2
  132. reconcile/terraform_repo.py +11 -14
  133. reconcile/terraform_resources.py +20 -21
  134. reconcile/terraform_tgw_attachments.py +32 -36
  135. reconcile/terraform_users.py +6 -7
  136. reconcile/terraform_vpc_resources/integration.py +6 -6
  137. reconcile/test/conftest.py +7 -10
  138. reconcile/test/fixtures.py +1 -1
  139. reconcile/test/saas_auto_promotions_manager/conftest.py +3 -2
  140. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +2 -2
  141. reconcile/test/test_database_access_manager.py +3 -6
  142. reconcile/test/test_gitlab_labeler.py +2 -5
  143. reconcile/test/test_jump_host.py +5 -8
  144. reconcile/test/test_ocm_machine_pools.py +1 -4
  145. reconcile/test/test_openshift_base.py +3 -6
  146. reconcile/test/test_openshift_cluster_bots.py +5 -5
  147. reconcile/test/test_openshift_namespace_labels.py +2 -3
  148. reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py +2 -2
  149. reconcile/test/test_saasherder.py +9 -12
  150. reconcile/test/test_slack_base.py +4 -6
  151. reconcile/test/test_status_board.py +4 -7
  152. reconcile/test/test_terraform_tgw_attachments.py +14 -20
  153. reconcile/typed_queries/alerting_services_settings.py +1 -2
  154. reconcile/typed_queries/app_interface_custom_messages.py +2 -3
  155. reconcile/typed_queries/app_interface_deadmanssnitch_settings.py +1 -3
  156. reconcile/typed_queries/app_interface_repo_url.py +1 -2
  157. reconcile/typed_queries/app_interface_state_settings.py +1 -3
  158. reconcile/typed_queries/app_interface_vault_settings.py +1 -2
  159. reconcile/typed_queries/aws_vpc_requests.py +1 -3
  160. reconcile/typed_queries/aws_vpcs.py +1 -3
  161. reconcile/typed_queries/clusters.py +2 -4
  162. reconcile/typed_queries/clusters_minimal.py +1 -3
  163. reconcile/typed_queries/clusters_with_dms.py +1 -3
  164. reconcile/typed_queries/dynatrace_environments.py +14 -0
  165. reconcile/typed_queries/external_resources.py +3 -4
  166. reconcile/typed_queries/pagerduty_instances.py +1 -2
  167. reconcile/typed_queries/repos.py +2 -3
  168. reconcile/typed_queries/reserved_networks.py +1 -3
  169. reconcile/typed_queries/saas_files.py +49 -59
  170. reconcile/typed_queries/slo_documents.py +1 -3
  171. reconcile/typed_queries/status_board.py +3 -7
  172. reconcile/typed_queries/tekton_pipeline_providers.py +1 -2
  173. reconcile/typed_queries/terraform_namespaces.py +1 -2
  174. reconcile/typed_queries/terraform_tgw_attachments/aws_accounts.py +1 -3
  175. reconcile/utils/acs/base.py +2 -3
  176. reconcile/utils/acs/notifiers.py +3 -3
  177. reconcile/utils/acs/policies.py +3 -3
  178. reconcile/utils/aggregated_list.py +1 -1
  179. reconcile/utils/amtool.py +1 -2
  180. reconcile/utils/aws_api.py +28 -31
  181. reconcile/utils/aws_api_typed/account.py +23 -0
  182. reconcile/utils/aws_api_typed/api.py +20 -9
  183. reconcile/utils/binary.py +1 -3
  184. reconcile/utils/clusterhealth/providerbase.py +1 -2
  185. reconcile/utils/clusterhealth/telemeter.py +2 -2
  186. reconcile/utils/deadmanssnitch_api.py +1 -2
  187. reconcile/utils/disabled_integrations.py +4 -6
  188. reconcile/utils/environ.py +1 -1
  189. reconcile/utils/expiration.py +3 -7
  190. reconcile/utils/external_resource_spec.py +3 -4
  191. reconcile/utils/external_resources.py +4 -7
  192. reconcile/utils/filtering.py +1 -2
  193. reconcile/utils/git.py +3 -9
  194. reconcile/utils/git_secrets.py +5 -5
  195. reconcile/utils/github_api.py +5 -9
  196. reconcile/utils/gitlab_api.py +2 -3
  197. reconcile/utils/glitchtip/client.py +2 -4
  198. reconcile/utils/glitchtip/models.py +8 -11
  199. reconcile/utils/gql.py +26 -35
  200. reconcile/utils/grouping.py +1 -3
  201. reconcile/utils/imap_client.py +2 -5
  202. reconcile/utils/internal_groups/client.py +1 -2
  203. reconcile/utils/internal_groups/models.py +8 -9
  204. reconcile/utils/jenkins_api.py +4 -4
  205. reconcile/utils/jinja2/extensions.py +1 -1
  206. reconcile/utils/jinja2/filters.py +4 -4
  207. reconcile/utils/jinja2/utils.py +16 -16
  208. reconcile/utils/jira_client.py +10 -11
  209. reconcile/utils/jjb_client.py +14 -17
  210. reconcile/utils/jobcontroller/controller.py +5 -5
  211. reconcile/utils/jobcontroller/models.py +2 -2
  212. reconcile/utils/jsonpath.py +4 -5
  213. reconcile/utils/jump_host.py +7 -8
  214. reconcile/utils/keycloak.py +3 -7
  215. reconcile/utils/ldap_client.py +2 -3
  216. reconcile/utils/lean_terraform_client.py +13 -17
  217. reconcile/utils/membershipsources/app_interface_resolver.py +1 -1
  218. reconcile/utils/membershipsources/models.py +19 -22
  219. reconcile/utils/metrics.py +13 -15
  220. reconcile/utils/mr/base.py +7 -11
  221. reconcile/utils/mr/glitchtip_access_reporter.py +2 -2
  222. reconcile/utils/mr/notificator.py +1 -2
  223. reconcile/utils/oc.py +38 -38
  224. reconcile/utils/oc_connection_parameters.py +24 -25
  225. reconcile/utils/oc_filters.py +2 -3
  226. reconcile/utils/oc_map.py +9 -15
  227. reconcile/utils/ocm/addons.py +7 -10
  228. reconcile/utils/ocm/base.py +38 -39
  229. reconcile/utils/ocm/clusters.py +6 -9
  230. reconcile/utils/ocm/label_sources.py +1 -2
  231. reconcile/utils/ocm/labels.py +3 -6
  232. reconcile/utils/ocm/ocm.py +11 -14
  233. reconcile/utils/ocm/products.py +1 -3
  234. reconcile/utils/ocm/search_filters.py +16 -17
  235. reconcile/utils/ocm/service_log.py +2 -3
  236. reconcile/utils/ocm/sre_capability_labels.py +4 -8
  237. reconcile/utils/ocm/subscriptions.py +1 -3
  238. reconcile/utils/ocm/syncsets.py +2 -4
  239. reconcile/utils/ocm/upgrades.py +5 -9
  240. reconcile/utils/ocm_base_client.py +13 -16
  241. reconcile/utils/openshift_resource.py +5 -11
  242. reconcile/utils/output.py +2 -3
  243. reconcile/utils/pagerduty_api.py +4 -5
  244. reconcile/utils/prometheus.py +2 -2
  245. reconcile/utils/promotion_state.py +4 -5
  246. reconcile/utils/promtool.py +2 -8
  247. reconcile/utils/quay_api.py +12 -22
  248. reconcile/utils/raw_github_api.py +3 -5
  249. reconcile/utils/rosa/rosa_cli.py +6 -6
  250. reconcile/utils/rosa/session.py +6 -7
  251. reconcile/utils/runtime/desired_state_diff.py +3 -8
  252. reconcile/utils/runtime/environment.py +4 -7
  253. reconcile/utils/runtime/integration.py +4 -4
  254. reconcile/utils/runtime/meta.py +1 -2
  255. reconcile/utils/runtime/runner.py +7 -10
  256. reconcile/utils/runtime/sharding.py +22 -27
  257. reconcile/utils/saasherder/interfaces.py +63 -69
  258. reconcile/utils/saasherder/models.py +30 -35
  259. reconcile/utils/saasherder/saasherder.py +39 -54
  260. reconcile/utils/secret_reader.py +17 -19
  261. reconcile/utils/slack_api.py +15 -17
  262. reconcile/utils/smtp_client.py +1 -2
  263. reconcile/utils/sqs_gateway.py +1 -3
  264. reconcile/utils/state.py +1 -2
  265. reconcile/utils/terraform/config_client.py +4 -5
  266. reconcile/utils/terraform_client.py +12 -8
  267. reconcile/utils/terrascript/cloudflare_client.py +4 -10
  268. reconcile/utils/terrascript/cloudflare_resources.py +10 -13
  269. reconcile/utils/terrascript/models.py +2 -3
  270. reconcile/utils/terrascript/resources.py +1 -2
  271. reconcile/utils/terrascript_aws_client.py +50 -38
  272. reconcile/utils/unleash/client.py +4 -7
  273. reconcile/utils/unleash/server.py +2 -2
  274. reconcile/utils/vault.py +8 -11
  275. reconcile/utils/vaultsecretref.py +2 -3
  276. reconcile/utils/vcs.py +7 -8
  277. reconcile/vault_replication.py +4 -8
  278. reconcile/vpc_peerings_validator.py +4 -9
  279. release/version.py +6 -7
  280. tools/app_interface_reporter.py +2 -2
  281. tools/cli_commands/gpg_encrypt.py +3 -6
  282. tools/cli_commands/systems_and_tools.py +4 -7
  283. tools/qontract_cli.py +105 -17
  284. tools/saas_promotion_state/__init__.py +0 -0
  285. tools/saas_promotion_state/saas_promotion_state.py +105 -0
  286. tools/template_validation.py +1 -1
  287. tools/test/conftest.py +45 -6
  288. tools/test/test_saas_promotion_state.py +187 -0
  289. {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/WHEEL +0 -0
  290. {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/entry_points.txt +0 -0
  291. {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/top_level.txt +0 -0
reconcile/jira_watcher.py CHANGED
@@ -34,8 +34,8 @@ def format_message(server, key, data, event, previous_state=None, current_state=
34
34
  if previous_state and current_state
35
35
  else ""
36
36
  )
37
- url = "{}/browse/{}".format(server, key)
38
- return "{} ({}) {}{}".format(url, summary, event, info)
37
+ url = f"{server}/browse/{key}"
38
+ return f"{url} ({summary}) {event}{info}"
39
39
 
40
40
 
41
41
  def calculate_diff(server, current_state, previous_state):
@@ -3,10 +3,7 @@ from collections.abc import (
3
3
  Callable,
4
4
  Iterable,
5
5
  )
6
- from typing import (
7
- Any,
8
- Optional,
9
- )
6
+ from typing import Any
10
7
 
11
8
  from reconcile.gql_definitions.ldap_groups.roles import RoleV1
12
9
  from reconcile.gql_definitions.ldap_groups.roles import query as roles_query
@@ -62,7 +59,7 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
62
59
  return {"roles": [c.dict() for c in self.get_roles(query_func)]}
63
60
 
64
61
  @defer
65
- def run(self, dry_run: bool, defer: Optional[Callable] = None) -> None:
62
+ def run(self, dry_run: bool, defer: Callable | None = None) -> None:
66
63
  """Run the integration."""
67
64
  gql_api = gql.get_api()
68
65
  roles = self.get_roles(gql_api.query)
reconcile/ocm/types.py CHANGED
@@ -1,10 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import (
4
- Optional,
5
- Union,
6
- )
7
-
8
3
  from pydantic import (
9
4
  BaseModel,
10
5
  Extra,
@@ -18,29 +13,29 @@ class OCMClusterAutoscale(BaseModel):
18
13
 
19
14
 
20
15
  class OCMClusterNetwork(BaseModel):
21
- type: Optional[str]
16
+ type: str | None
22
17
  vpc: str
23
18
  service: str
24
19
  pod: str
25
20
 
26
21
 
27
22
  class OCMClusterSpec(BaseModel):
28
- autoscale: Optional[OCMClusterAutoscale]
23
+ autoscale: OCMClusterAutoscale | None
29
24
  channel: str
30
- disable_user_workload_monitoring: Optional[bool]
31
- external_id: Optional[str]
32
- id: Optional[str]
33
- instance_type: Optional[str]
34
- multi_az: Optional[bool]
35
- nodes: Optional[int]
25
+ disable_user_workload_monitoring: bool | None
26
+ external_id: str | None
27
+ id: str | None
28
+ instance_type: str | None
29
+ multi_az: bool | None
30
+ nodes: int | None
36
31
  private: bool
37
32
  product: str
38
33
  provider: str
39
- provision_shard_id: Optional[str]
34
+ provision_shard_id: str | None
40
35
  region: str
41
- initial_version: Optional[str]
36
+ initial_version: str | None
42
37
  version: str
43
- hypershift: Optional[bool]
38
+ hypershift: bool | None
44
39
 
45
40
  class Config:
46
41
  extra = Extra.forbid
@@ -57,7 +52,7 @@ class OSDClusterSpec(OCMClusterSpec):
57
52
  class ROSAOcmAwsStsAttrs(BaseModel):
58
53
  installer_role_arn: str
59
54
  support_role_arn: str
60
- controlplane_role_arn: Optional[str]
55
+ controlplane_role_arn: str | None
61
56
  worker_role_arn: str
62
57
 
63
58
  class Config:
@@ -66,7 +61,7 @@ class ROSAOcmAwsStsAttrs(BaseModel):
66
61
 
67
62
  class ROSAOcmAwsAttrs(BaseModel):
68
63
  creator_role_arn: str
69
- sts: Optional[ROSAOcmAwsStsAttrs]
64
+ sts: ROSAOcmAwsStsAttrs | None
70
65
 
71
66
  class Config:
72
67
  extra = Extra.forbid
@@ -82,9 +77,9 @@ class ROSAClusterAWSAccount(BaseModel):
82
77
 
83
78
  class ROSAClusterSpec(OCMClusterSpec):
84
79
  account: ROSAClusterAWSAccount
85
- subnet_ids: Optional[list[str]]
86
- availability_zones: Optional[list[str]]
87
- oidc_endpoint_url: Optional[str]
80
+ subnet_ids: list[str] | None
81
+ availability_zones: list[str] | None
82
+ oidc_endpoint_url: str | None
88
83
 
89
84
  class Config:
90
85
  extra = Extra.forbid
@@ -93,18 +88,18 @@ class ROSAClusterSpec(OCMClusterSpec):
93
88
  class ClusterMachinePool(BaseModel):
94
89
  id: str
95
90
  instance_type: str
96
- replicas: Optional[int]
97
- autoscale: Optional[OCMClusterAutoscale]
91
+ replicas: int | None
92
+ autoscale: OCMClusterAutoscale | None
98
93
 
99
94
 
100
95
  class OCMSpec(BaseModel):
101
- path: Optional[str]
102
- spec: Union[OSDClusterSpec, ROSAClusterSpec, OCMClusterSpec]
96
+ path: str | None
97
+ spec: OSDClusterSpec | ROSAClusterSpec | OCMClusterSpec
103
98
  machine_pools: list[ClusterMachinePool] = Field(
104
99
  default_factory=list, alias="machinePools"
105
100
  )
106
101
  network: OCMClusterNetwork
107
- domain: Optional[str]
102
+ domain: str | None
108
103
  server_url: str = Field("", alias="serverUrl")
109
104
  console_url: str = Field("", alias="consoleUrl")
110
105
  elb_fqdn: str = Field("", alias="elbFQDN")
@@ -1,8 +1,5 @@
1
1
  import logging
2
- from typing import (
3
- Callable,
4
- Optional,
5
- )
2
+ from collections.abc import Callable
6
3
 
7
4
  from reconcile import queries
8
5
  from reconcile.typed_queries.app_interface_vault_settings import (
@@ -18,7 +15,7 @@ QONTRACT_INTEGRATION = "ocm-addons-upgrade-tests-trigger"
18
15
 
19
16
 
20
17
  @defer
21
- def run(dry_run: bool, defer: Optional[Callable] = None) -> None:
18
+ def run(dry_run: bool, defer: Callable | None = None) -> None:
22
19
  settings = queries.get_app_interface_settings()
23
20
  vault_settings = get_app_interface_vault_settings()
24
21
  secret_reader = create_secret_reader(use_vault=vault_settings.vault)
@@ -40,7 +37,7 @@ def run(dry_run: bool, defer: Optional[Callable] = None) -> None:
40
37
  )
41
38
 
42
39
  ocm = ocm_map[ocm_name]
43
- state_updates: dict[str, Optional[str]] = {}
40
+ state_updates: dict[str, str | None] = {}
44
41
  for aut in addon_upgrade_tests:
45
42
  addon_name = aut["addon"]["name"]
46
43
  addon_org_version = None
reconcile/ocm_clusters.py CHANGED
@@ -4,7 +4,7 @@ from collections.abc import (
4
4
  Iterable,
5
5
  Mapping,
6
6
  )
7
- from typing import Any, Optional
7
+ from typing import Any
8
8
 
9
9
  import reconcile.utils.mr.clusters_updates as cu
10
10
  import reconcile.utils.ocm as ocmmod
@@ -283,7 +283,7 @@ def get_cluster_ocm_update_spec(
283
283
 
284
284
 
285
285
  def _app_interface_updates_mr(
286
- clusters_updates: Mapping[str, Any], gitlab_project_id: Optional[str], dry_run: bool
286
+ clusters_updates: Mapping[str, Any], gitlab_project_id: str | None, dry_run: bool
287
287
  ):
288
288
  """Creates an MR to app-interface with the necessary cluster manifest updates
289
289
 
@@ -318,15 +318,15 @@ def _cluster_is_compatible(cluster: Mapping[str, Any]) -> bool:
318
318
 
319
319
 
320
320
  class OcmClustersParams(PydanticRunParams):
321
- gitlab_project_id: Optional[str] = None
321
+ gitlab_project_id: str | None = None
322
322
  thread_pool_size: int = 10
323
323
 
324
324
  # rosa job controller params
325
- job_controller_cluster: Optional[str] = None
326
- job_controller_namespace: Optional[str] = None
327
- rosa_job_service_account: Optional[str] = None
328
- rosa_role: Optional[str] = None
329
- rosa_job_image: Optional[str] = None
325
+ job_controller_cluster: str | None = None
326
+ job_controller_namespace: str | None = None
327
+ rosa_job_service_account: str | None = None
328
+ rosa_role: str | None = None
329
+ rosa_job_image: str | None = None
330
330
 
331
331
 
332
332
  class OcmClusters(QontractReconcileIntegration[OcmClustersParams]):
@@ -5,7 +5,6 @@ from collections.abc import (
5
5
  Callable,
6
6
  )
7
7
  from functools import lru_cache
8
- from typing import Optional
9
8
 
10
9
  from reconcile.gql_definitions.common.ocm_environments import (
11
10
  query as ocm_environment_query,
@@ -48,7 +47,7 @@ class OcmInternalNotifications(QontractReconcileIntegration[NoParams]):
48
47
  @lru_cache
49
48
  def slack_get_user_id_by_name(
50
49
  self, user_name: str, mail_address: str
51
- ) -> Optional[str]:
50
+ ) -> str | None:
52
51
  try:
53
52
  return self.slack.get_user_id_by_name(
54
53
  user_name=user_name, mail_address=mail_address
@@ -5,10 +5,7 @@ from collections.abc import (
5
5
  Callable,
6
6
  Iterable,
7
7
  )
8
- from typing import (
9
- Any,
10
- Optional,
11
- )
8
+ from typing import Any
12
9
 
13
10
  from deepdiff import DeepHash
14
11
  from pydantic import validator
@@ -124,7 +121,7 @@ class OcmLabelsIntegration(QontractReconcileIntegration[OcmLabelsIntegrationPara
124
121
  init_aus_cluster_label_source(query_func),
125
122
  ]
126
123
 
127
- def get_early_exit_desired_state(self) -> Optional[dict[str, Any]]:
124
+ def get_early_exit_desired_state(self) -> dict[str, Any] | None:
128
125
  gqlapi = gql.get_api()
129
126
  desired = {
130
127
  "org_labels": self.fetch_desired_state(
@@ -3,12 +3,8 @@ from abc import (
3
3
  ABC,
4
4
  abstractmethod,
5
5
  )
6
- from collections.abc import Mapping
6
+ from collections.abc import Iterable, Mapping
7
7
  from enum import Enum
8
- from typing import (
9
- Iterable,
10
- Optional,
11
- )
12
8
 
13
9
  from pydantic import (
14
10
  BaseModel,
@@ -100,12 +96,12 @@ class AbstractPool(ABC, BaseModel):
100
96
  # Abstract class for machine pools, to be implemented by OSD/HyperShift classes
101
97
 
102
98
  id: str
103
- replicas: Optional[int]
104
- taints: Optional[list[Mapping[str, str]]]
105
- labels: Optional[Mapping[str, str]]
99
+ replicas: int | None
100
+ taints: list[Mapping[str, str]] | None
101
+ labels: Mapping[str, str] | None
106
102
  cluster: str
107
103
  cluster_type: ClusterType = Field(..., exclude=True)
108
- autoscaling: Optional[AbstractAutoscaling]
104
+ autoscaling: AbstractAutoscaling | None
109
105
 
110
106
  @root_validator()
111
107
  @classmethod
@@ -131,7 +127,7 @@ class AbstractPool(ABC, BaseModel):
131
127
  pass
132
128
 
133
129
  @abstractmethod
134
- def invalid_diff(self, pool: ClusterMachinePoolV1) -> Optional[str]:
130
+ def invalid_diff(self, pool: ClusterMachinePoolV1) -> str | None:
135
131
  pass
136
132
 
137
133
  @abstractmethod
@@ -184,7 +180,7 @@ class MachinePool(AbstractPool):
184
180
  or self._has_diff_autoscale(pool)
185
181
  )
186
182
 
187
- def invalid_diff(self, pool: ClusterMachinePoolV1) -> Optional[str]:
183
+ def invalid_diff(self, pool: ClusterMachinePoolV1) -> str | None:
188
184
  if self.instance_type != pool.instance_type:
189
185
  return "instance_type"
190
186
  return None
@@ -203,7 +199,7 @@ class MachinePool(AbstractPool):
203
199
  cluster: str,
204
200
  cluster_type: ClusterType,
205
201
  ):
206
- autoscaling: Optional[MachinePoolAutoscaling] = None
202
+ autoscaling: MachinePoolAutoscaling | None = None
207
203
  if pool.autoscale:
208
204
  autoscaling = MachinePoolAutoscaling(
209
205
  min_replicas=pool.autoscale.min_replicas,
@@ -229,7 +225,7 @@ class NodePool(AbstractPool):
229
225
  # Node pool, used for HyperShift clusters
230
226
 
231
227
  aws_node_pool: AWSNodePool
232
- subnet: Optional[str]
228
+ subnet: str | None
233
229
 
234
230
  def delete(self, ocm: OCM) -> None:
235
231
  ocm.delete_node_pool(self.cluster, self.dict(by_alias=True))
@@ -266,7 +262,7 @@ class NodePool(AbstractPool):
266
262
  or self._has_diff_autoscale(pool)
267
263
  )
268
264
 
269
- def invalid_diff(self, pool: ClusterMachinePoolV1) -> Optional[str]:
265
+ def invalid_diff(self, pool: ClusterMachinePoolV1) -> str | None:
270
266
  if self.aws_node_pool.instance_type != pool.instance_type:
271
267
  return "instance_type"
272
268
  if self.subnet != pool.subnet:
@@ -283,7 +279,7 @@ class NodePool(AbstractPool):
283
279
  cluster: str,
284
280
  cluster_type: ClusterType,
285
281
  ):
286
- autoscaling: Optional[NodePoolAutoscaling] = None
282
+ autoscaling: NodePoolAutoscaling | None = None
287
283
  if pool.autoscale:
288
284
  autoscaling = NodePoolAutoscaling(
289
285
  min_replica=pool.autoscale.min_replicas,
@@ -1,9 +1,6 @@
1
1
  import json
2
2
  import logging
3
- from typing import (
4
- Any,
5
- Optional,
6
- )
3
+ from typing import Any
7
4
 
8
5
  import yaml
9
6
 
@@ -25,7 +22,7 @@ def render_policy(
25
22
  template: dict[str, Any],
26
23
  cluster_spec: OCMSpec,
27
24
  labels: dict[str, str],
28
- settings: Optional[dict[str, Any]] = None,
25
+ settings: dict[str, Any] | None = None,
29
26
  ) -> dict[str, Any]:
30
27
  body = template["path"]["content"]
31
28
  type = template.get("type") or "jinja2"
@@ -12,9 +12,7 @@ from dataclasses import (
12
12
  )
13
13
  from typing import (
14
14
  Any,
15
- Optional,
16
15
  Protocol,
17
- Union,
18
16
  runtime_checkable,
19
17
  )
20
18
 
@@ -40,6 +38,7 @@ from reconcile.utils.oc import (
40
38
  OCClient,
41
39
  OCLogMsg,
42
40
  PrimaryClusterIPCanNotBeUnsetError,
41
+ RequestEntityTooLargeError,
43
42
  StatefulSetUpdateForbidden,
44
43
  StatusCodeError,
45
44
  UnsupportedMediaTypeError,
@@ -73,7 +72,7 @@ class BaseStateSpec:
73
72
  @dataclass
74
73
  class CurrentStateSpec(BaseStateSpec):
75
74
  kind: str
76
- resource_names: Optional[Iterable[str]]
75
+ resource_names: Iterable[str] | None
77
76
 
78
77
 
79
78
  @dataclass
@@ -83,7 +82,7 @@ class DesiredStateSpec(BaseStateSpec):
83
82
  privileged: bool = False
84
83
 
85
84
 
86
- StateSpec = Union[CurrentStateSpec, DesiredStateSpec]
85
+ StateSpec = CurrentStateSpec | DesiredStateSpec
87
86
 
88
87
 
89
88
  @runtime_checkable
@@ -113,7 +112,7 @@ class HasOrgAndGithubUsername(Protocol):
113
112
  class ClusterMap(Protocol):
114
113
  """An OCMap protocol."""
115
114
 
116
- def get(self, cluster: str, privileged: bool = False) -> Union[OCCli, OCLogMsg]: ...
115
+ def get(self, cluster: str, privileged: bool = False) -> OCCli | OCLogMsg: ...
117
116
 
118
117
  def get_cluster(self, cluster: str, privileged: bool = False) -> OCCli: ...
119
118
 
@@ -125,9 +124,9 @@ class ClusterMap(Protocol):
125
124
  def init_specs_to_fetch(
126
125
  ri: ResourceInventory,
127
126
  oc_map: ClusterMap,
128
- namespaces: Optional[Iterable[Mapping]] = None,
129
- clusters: Optional[Iterable[Mapping]] = None,
130
- override_managed_types: Optional[Iterable[str]] = None,
127
+ namespaces: Iterable[Mapping] | None = None,
128
+ clusters: Iterable[Mapping] | None = None,
129
+ override_managed_types: Iterable[str] | None = None,
131
130
  managed_types_key: str = "managedResourceTypes",
132
131
  ) -> list[StateSpec]:
133
132
  state_specs: list[StateSpec] = []
@@ -288,7 +287,7 @@ def populate_current_state(
288
287
  ri: ResourceInventory,
289
288
  integration: str,
290
289
  integration_version: str,
291
- caller: Optional[str] = None,
290
+ caller: str | None = None,
292
291
  ):
293
292
  # if spec.oc is None: - oc can't be none because init_namespace_specs_to_fetch does not create specs if oc is none
294
293
  # return
@@ -318,17 +317,17 @@ def populate_current_state(
318
317
 
319
318
 
320
319
  def fetch_current_state(
321
- namespaces: Optional[Iterable[Mapping]] = None,
322
- clusters: Optional[Iterable[Mapping]] = None,
323
- thread_pool_size: Optional[int] = None,
324
- integration: Optional[str] = None,
325
- integration_version: Optional[str] = None,
326
- override_managed_types: Optional[Iterable[str]] = None,
327
- internal: Optional[bool] = None,
320
+ namespaces: Iterable[Mapping] | None = None,
321
+ clusters: Iterable[Mapping] | None = None,
322
+ thread_pool_size: int | None = None,
323
+ integration: str | None = None,
324
+ integration_version: str | None = None,
325
+ override_managed_types: Iterable[str] | None = None,
326
+ internal: bool | None = None,
328
327
  use_jump_host: bool = True,
329
328
  init_api_resources: bool = False,
330
329
  cluster_admin: bool = False,
331
- caller: Optional[str] = None,
330
+ caller: str | None = None,
332
331
  ) -> tuple[ResourceInventory, OC_Map]:
333
332
  ri = ResourceInventory()
334
333
  settings = queries.get_app_interface_settings()
@@ -402,7 +401,7 @@ def apply(
402
401
 
403
402
  try:
404
403
  oc.apply(namespace, annotated)
405
- except InvalidValueApplyError:
404
+ except (InvalidValueApplyError, RequestEntityTooLargeError):
406
405
  oc.remove_last_applied_configuration(
407
406
  namespace, resource_type, resource.name
408
407
  )
@@ -567,11 +566,11 @@ class ApplyOptions:
567
566
  wait_for_namespace: bool
568
567
  recycle_pods: bool
569
568
  take_over: bool
570
- override_enable_deletion: Optional[bool]
571
- caller: Optional[str]
572
- all_callers: Optional[Sequence[str]]
573
- privileged: Optional[bool]
574
- enable_deletion: Optional[bool]
569
+ override_enable_deletion: bool | None
570
+ caller: str | None
571
+ all_callers: Sequence[str] | None
572
+ privileged: bool | None
573
+ enable_deletion: bool | None
575
574
 
576
575
 
577
576
  def should_apply(
@@ -886,7 +885,7 @@ def delete_action(
886
885
  )
887
886
  except StatusCodeError as e:
888
887
  ri.register_error()
889
- msg = "[{}/{}] {}".format(cluster, namespace, str(e))
888
+ msg = f"[{cluster}/{namespace}] {str(e)}"
890
889
  logging.error(msg)
891
890
 
892
891
 
@@ -931,7 +930,7 @@ def _realize_resource_data_3way_diff(
931
930
  actions: list[dict] = []
932
931
 
933
932
  if ri.has_error_registered(cluster=cluster):
934
- msg = ("[{}] skipping realize_data for " "cluster with errors").format(cluster)
933
+ msg = f"[{cluster}] skipping realize_data for " "cluster with errors"
935
934
  logging.error(msg)
936
935
  return actions
937
936
 
@@ -1305,8 +1304,8 @@ def aggregate_shared_resources(namespace_info, shared_resources_type):
1305
1304
 
1306
1305
  def determine_user_keys_for_access(
1307
1306
  cluster_name: str,
1308
- auth_list: Sequence[Union[dict[str, str], HasService]],
1309
- enforced_user_keys: Optional[list[str]] = None,
1307
+ auth_list: Sequence[dict[str, str] | HasService],
1308
+ enforced_user_keys: list[str] | None = None,
1310
1309
  ) -> list[str]:
1311
1310
  """Return user keys based on enabled cluster authentication methods."""
1312
1311
  AUTH_METHOD_USER_KEY = {
@@ -1352,7 +1351,7 @@ def user_has_cluster_access(
1352
1351
  ) -> bool:
1353
1352
  """Check user has access to cluster."""
1354
1353
  userkeys = determine_user_keys_for_access(cluster.name, cluster.auth)
1355
- return any((getattr(user, userkey) in cluster_users for userkey in userkeys))
1354
+ return any(getattr(user, userkey) in cluster_users for userkey in userkeys)
1356
1355
 
1357
1356
 
1358
1357
  def get_namespace_type_overrides(namespace: Mapping) -> dict[str, str]:
@@ -1368,7 +1367,7 @@ def get_namespace_type_overrides(namespace: Mapping) -> dict[str, str]:
1368
1367
 
1369
1368
 
1370
1369
  def get_namespace_resource_types(
1371
- namespace: Mapping, type_overrides: Optional[dict[str, str]] = None
1370
+ namespace: Mapping, type_overrides: dict[str, str] | None = None
1372
1371
  ) -> list[str]:
1373
1372
  """Returns a list with the namespace ResourceTypes, with the overrides in place
1374
1373
 
@@ -1385,7 +1384,7 @@ def get_namespace_resource_types(
1385
1384
 
1386
1385
 
1387
1386
  def get_namespace_resource_names(
1388
- namespace: Mapping, type_overrides: Optional[dict[str, str]] = None
1387
+ namespace: Mapping, type_overrides: dict[str, str] | None = None
1389
1388
  ) -> dict[str, list[str]]:
1390
1389
  """Returns a list with the namespace ResourceTypeNames, with the overrides in place
1391
1390
 
@@ -5,10 +5,7 @@ from collections.abc import (
5
5
  Iterable,
6
6
  Mapping,
7
7
  )
8
- from typing import (
9
- Any,
10
- Optional,
11
- )
8
+ from typing import Any
12
9
 
13
10
  from sretoolbox.utils import threaded
14
11
 
@@ -53,9 +50,7 @@ def get_cluster_state(
53
50
  try:
54
51
  group = oc.get_group_if_exists(group_name)
55
52
  except Exception as e:
56
- msg = ("could not get group state for cluster/group combination: {}/{}").format(
57
- cluster, group_name
58
- )
53
+ msg = f"could not get group state for cluster/group combination: {cluster}/{group_name}"
59
54
  logging.error(msg)
60
55
  raise e
61
56
  if group is None:
@@ -84,7 +79,7 @@ def create_groups_list(
84
79
 
85
80
 
86
81
  def fetch_current_state(
87
- thread_pool_size: int, internal: Optional[bool], use_jump_host: bool
82
+ thread_pool_size: int, internal: bool | None, use_jump_host: bool
88
83
  ) -> tuple[OCMap, list[dict[str, str]], list[str], list[dict[str, str]]]:
89
84
  clusters = [c for c in get_clusters() if is_in_shard(c.name)]
90
85
  ocm_clusters = [c.name for c in clusters if c.ocm is not None]
@@ -110,7 +105,7 @@ def fetch_current_state(
110
105
 
111
106
 
112
107
  def fetch_desired_state(
113
- clusters: list[str], enforced_user_keys: Optional[list[str]] = None
108
+ clusters: list[str], enforced_user_keys: list[str] | None = None
114
109
  ) -> list[dict[str, str]]:
115
110
  gqlapi = gql.get_api()
116
111
  roles = expiration.filter(query_managed_roles(query_func=gqlapi.query).roles or [])
@@ -145,8 +140,8 @@ def fetch_desired_state(
145
140
  def calculate_diff(
146
141
  current_state: Iterable[Mapping[str, str]],
147
142
  desired_state: Iterable[Mapping[str, str]],
148
- ) -> list[dict[str, Optional[str]]]:
149
- diff: list[dict[str, Optional[str]]] = []
143
+ ) -> list[dict[str, str | None]]:
144
+ diff: list[dict[str, str | None]] = []
150
145
  users_to_add = subtract_states(
151
146
  desired_state, current_state, "add_user_to_group", "create_group"
152
147
  )
@@ -164,8 +159,8 @@ def subtract_states(
164
159
  subtract_state: Iterable[Mapping[str, str]],
165
160
  user_action: str,
166
161
  group_action: str,
167
- ) -> list[dict[str, Optional[str]]]:
168
- result: list[dict[str, Optional[str]]] = []
162
+ ) -> list[dict[str, str | None]]:
163
+ result: list[dict[str, str | None]] = []
169
164
 
170
165
  for f_user in from_state:
171
166
  found = False
@@ -199,14 +194,14 @@ def subtract_states(
199
194
  return result
200
195
 
201
196
 
202
- def validate_diffs(diffs: Iterable[Mapping[str, Optional[str]]]) -> None:
197
+ def validate_diffs(diffs: Iterable[Mapping[str, str | None]]) -> None:
203
198
  gqlapi = gql.get_api()
204
199
  clusters_query = query_managed_groups(query_func=gqlapi.query).clusters or []
205
200
 
206
201
  desired_combos = [
207
202
  {"cluster": diff["cluster"], "group": diff["group"]} for diff in diffs
208
203
  ]
209
- desired_combos_unique: list[dict[str, Optional[str]]] = []
204
+ desired_combos_unique: list[dict[str, str | None]] = []
210
205
  for combo in desired_combos:
211
206
  if combo in desired_combos_unique:
212
207
  continue
@@ -232,13 +227,13 @@ def validate_diffs(diffs: Iterable[Mapping[str, Optional[str]]]) -> None:
232
227
  raise RuntimeError(msg)
233
228
 
234
229
 
235
- def sort_diffs(diff: Mapping[str, Optional[str]]) -> int:
230
+ def sort_diffs(diff: Mapping[str, str | None]) -> int:
236
231
  if diff["action"] in {"create_group", "del_user_from_group"}:
237
232
  return 1
238
233
  return 2
239
234
 
240
235
 
241
- def act(diff: Mapping[str, Optional[str]], oc_map: ClusterMap) -> None:
236
+ def act(diff: Mapping[str, str | None], oc_map: ClusterMap) -> None:
242
237
  cluster = diff.get("cluster") or ""
243
238
  group = diff["group"]
244
239
  user = diff["user"]
@@ -257,16 +252,16 @@ def act(diff: Mapping[str, Optional[str]], oc_map: ClusterMap) -> None:
257
252
  elif action == "delete_group":
258
253
  logging.debug("skipping group deletion")
259
254
  else:
260
- raise Exception("invalid action: {}".format(action))
255
+ raise Exception(f"invalid action: {action}")
261
256
 
262
257
 
263
258
  @defer
264
259
  def run(
265
260
  dry_run: bool,
266
261
  thread_pool_size: int = 10,
267
- internal: Optional[bool] = None,
262
+ internal: bool | None = None,
268
263
  use_jump_host: bool = True,
269
- defer: Optional[Callable] = None,
264
+ defer: Callable | None = None,
270
265
  ) -> None:
271
266
  oc_map, current_state, ocm_clusters, groups_list = fetch_current_state(
272
267
  thread_pool_size, internal, use_jump_host