qontract-reconcile 0.10.1rc884__py3-none-any.whl → 0.10.1rc885__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 (276) hide show
  1. {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/METADATA +1 -1
  2. {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/RECORD +276 -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 +12 -17
  272. tools/template_validation.py +1 -1
  273. tools/test/conftest.py +3 -6
  274. {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/WHEEL +0 -0
  275. {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/entry_points.txt +0 -0
  276. {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/top_level.txt +0 -0
@@ -3,10 +3,7 @@ import os
3
3
  from base64 import b64encode
4
4
  from collections.abc import Mapping
5
5
  from dataclasses import dataclass
6
- from typing import (
7
- Any,
8
- Optional,
9
- )
6
+ from typing import Any
10
7
  from urllib.parse import urljoin
11
8
 
12
9
  import requests
@@ -23,8 +20,8 @@ LOG = logging.getLogger(__name__)
23
20
  class DashdotDBSecret:
24
21
  path: str
25
22
  field: str
26
- q_format: Optional[str]
27
- version: Optional[int]
23
+ q_format: str | None
24
+ version: int | None
28
25
 
29
26
 
30
27
  DASHDOTDB_SECRET = DashdotDBSecret(
@@ -53,7 +50,7 @@ class DashdotdbBase:
53
50
  self.dashdotdb_pass = self.secret_content["password"]
54
51
  self.logmarker = marker
55
52
  self.scope = scope
56
- self.dashdotdb_token = Optional[str]
53
+ self.dashdotdb_token: str | None
57
54
 
58
55
  def _get_token(self) -> None:
59
56
  if self.dry_run:
@@ -134,10 +131,10 @@ class DashdotdbBase:
134
131
  def _promget(
135
132
  self,
136
133
  url: str,
137
- params: Optional[Mapping[Any, Any]],
138
- token: Optional[str] = None,
139
- username: Optional[str] = None,
140
- password: Optional[str] = None,
134
+ params: Mapping[Any, Any] | None,
135
+ token: str | None = None,
136
+ username: str | None = None,
137
+ password: str | None = None,
141
138
  ssl_verify: bool = True,
142
139
  uri: str = "api/v1/query",
143
140
  ) -> dict[Any, Any]:
@@ -1,7 +1,4 @@
1
- from typing import (
2
- Any,
3
- Optional,
4
- )
1
+ from typing import Any
5
2
 
6
3
  import requests
7
4
  from sretoolbox.utils import threaded
@@ -44,7 +41,7 @@ class DashdotdbCSO(DashdotdbBase):
44
41
  secret_reader=secret_reader,
45
42
  )
46
43
 
47
- def _post(self, manifest: dict[Any, Any]) -> Optional[requests.Response]:
44
+ def _post(self, manifest: dict[Any, Any]) -> requests.Response | None:
48
45
  if manifest is None:
49
46
  return None
50
47
 
@@ -70,7 +67,7 @@ class DashdotdbCSO(DashdotdbBase):
70
67
  return response
71
68
 
72
69
  @staticmethod
73
- def _get_imagemanifestvuln(cluster: str, oc_map: OCMap) -> Optional[dict[str, Any]]:
70
+ def _get_imagemanifestvuln(cluster: str, oc_map: OCMap) -> dict[str, Any] | None:
74
71
  LOG.info("%s processing %s", LOGMARKER, cluster)
75
72
  oc = oc_map.get(cluster)
76
73
  if isinstance(oc, OCLogMsg):
@@ -1,17 +1,15 @@
1
1
  import functools
2
2
  import os
3
3
  from collections import defaultdict
4
+ from collections.abc import Iterable, Mapping
4
5
  from dataclasses import dataclass
5
6
  from datetime import (
7
+ UTC,
6
8
  datetime,
7
9
  timedelta,
8
- timezone,
9
10
  )
10
11
  from typing import (
11
12
  Any,
12
- Iterable,
13
- Mapping,
14
- Optional,
15
13
  Self,
16
14
  )
17
15
 
@@ -44,8 +42,8 @@ QONTRACT_INTEGRATION = "dashdotdb-dora"
44
42
  class DeploymentDBSecret:
45
43
  path: str
46
44
  field: str
47
- q_format: Optional[str]
48
- version: Optional[int]
45
+ q_format: str | None
46
+ version: int | None
49
47
 
50
48
 
51
49
  @dataclass(eq=True, frozen=True)
@@ -76,9 +74,9 @@ class SaasTarget:
76
74
 
77
75
  @dataclass(eq=True, frozen=True)
78
76
  class RepoChanges:
79
- repo_url: Optional[str]
80
- ref_from: Optional[str]
81
- ref_to: Optional[str]
77
+ repo_url: str | None
78
+ ref_from: str | None
79
+ ref_to: str | None
82
80
 
83
81
 
84
82
  @dataclass(eq=True, frozen=True)
@@ -162,12 +160,10 @@ class Commit:
162
160
  finish_timestamp_tzaware = finish_timestamp
163
161
 
164
162
  if commit_date_tzaware.tzinfo is None:
165
- commit_date_tzaware = commit_date_tzaware.replace(tzinfo=timezone.utc)
163
+ commit_date_tzaware = commit_date_tzaware.replace(tzinfo=UTC)
166
164
 
167
165
  if finish_timestamp_tzaware.tzinfo is None:
168
- finish_timestamp_tzaware = finish_timestamp_tzaware.replace(
169
- tzinfo=timezone.utc
170
- )
166
+ finish_timestamp_tzaware = finish_timestamp_tzaware.replace(tzinfo=UTC)
171
167
 
172
168
  return int((finish_timestamp_tzaware - commit_date_tzaware).total_seconds())
173
169
 
@@ -397,7 +393,7 @@ class DashdotdbDORA(DashdotdbBase):
397
393
 
398
394
  def get_repo_ref_for_sha(
399
395
  self, saastarget: SaasTarget, sha: str
400
- ) -> tuple[Optional[str], Optional[str]]:
396
+ ) -> tuple[str | None, str | None]:
401
397
  try:
402
398
  saas_file_yaml = self.gl_app_interface_get_file(
403
399
  saastarget.path, ref=sha
@@ -4,10 +4,7 @@ from collections.abc import (
4
4
  Sequence,
5
5
  )
6
6
  from dataclasses import dataclass
7
- from typing import (
8
- Any,
9
- Optional,
10
- )
7
+ from typing import Any
11
8
 
12
9
  import requests
13
10
  from requests import Response
@@ -67,7 +64,7 @@ class DashdotdbDVO(DashdotdbBase):
67
64
  for i in range(0, len(data), int(size)):
68
65
  yield data[i : i + int(size)]
69
66
 
70
- def _post(self, deploymentvalidation: DVOPayload) -> Optional[Response]:
67
+ def _post(self, deploymentvalidation: DVOPayload) -> Response | None:
71
68
  if deploymentvalidation is None:
72
69
  return
73
70
  cluster_name = deploymentvalidation.cluster_name
@@ -130,7 +127,7 @@ class DashdotdbDVO(DashdotdbBase):
130
127
 
131
128
  def _get_deploymentvalidation(
132
129
  self, metrics: list[str], cluster: ClusterV1
133
- ) -> Optional[DVOPayload]:
130
+ ) -> DVOPayload | None:
134
131
  prom_info = self._get_prometheus_info(cluster)
135
132
  if not prom_info:
136
133
  return None
@@ -162,8 +159,8 @@ class DashdotdbDVO(DashdotdbBase):
162
159
  # via startswith and return only those that match.
163
160
  # Returns a map of {cluster: cluster_name, data: [metric_names]}
164
161
  def _get_validation_names(
165
- self, cluster: ClusterV1, filter: Optional[str] = None
166
- ) -> Optional[ClusterValidationMetrics]:
162
+ self, cluster: ClusterV1, filter: str | None = None
163
+ ) -> ClusterValidationMetrics | None:
167
164
  prom_info = self._get_prometheus_info(cluster)
168
165
  if not prom_info:
169
166
  return None
@@ -202,7 +199,7 @@ class DashdotdbDVO(DashdotdbBase):
202
199
  metrics=deploymentvalidation["data"],
203
200
  )
204
201
 
205
- def _get_prometheus_info(self, cluster: ClusterV1) -> Optional[PrometheusInfo]:
202
+ def _get_prometheus_info(self, cluster: ClusterV1) -> PrometheusInfo | None:
206
203
  if not cluster.automation_token:
207
204
  LOG.error(
208
205
  "%s cluster %s does not have an automation token",
@@ -217,14 +214,14 @@ class DashdotdbDVO(DashdotdbBase):
217
214
  )
218
215
 
219
216
  @staticmethod
220
- def _get_clusters(name: Optional[str] = None) -> list[ClusterV1]:
217
+ def _get_clusters(name: str | None = None) -> list[ClusterV1]:
221
218
  return [
222
219
  c for c in get_clusters_minimal(name=name) if c.ocm and c.prometheus_url
223
220
  ]
224
221
 
225
- def run(self, cname: Optional[str] = None) -> None:
222
+ def run(self, cname: str | None = None) -> None:
226
223
  clusters = self._get_clusters(name=cname)
227
- validation_list: list[Optional[ClusterValidationMetrics]] = threaded.run(
224
+ validation_list: list[ClusterValidationMetrics | None] = threaded.run(
228
225
  func=self._get_validation_names,
229
226
  iterable=clusters,
230
227
  thread_pool_size=self.thread_pool_size,
@@ -258,7 +255,7 @@ class DashdotdbDVO(DashdotdbBase):
258
255
  def run(
259
256
  dry_run: bool = False,
260
257
  thread_pool_size: int = 10,
261
- cluster_name: Optional[str] = None,
258
+ cluster_name: str | None = None,
262
259
  ) -> None:
263
260
  vault_settings = get_app_interface_vault_settings()
264
261
  secret_reader = create_secret_reader(use_vault=vault_settings.vault)
@@ -1,9 +1,6 @@
1
1
  from collections.abc import Iterable
2
2
  from dataclasses import dataclass
3
- from typing import (
4
- Any,
5
- Optional,
6
- )
3
+ from typing import Any
7
4
 
8
5
  import jinja2
9
6
  import requests
@@ -72,7 +69,7 @@ class DashdotdbSLO(DashdotdbBase):
72
69
  secret_reader=secret_reader,
73
70
  )
74
71
 
75
- def _post(self, service_slos: Iterable[ServiceSLO]) -> Optional[Response]:
72
+ def _post(self, service_slos: Iterable[ServiceSLO]) -> Response | None:
76
73
  for item in service_slos:
77
74
  LOG.debug(f"About to POST SLO JSON item to dashdotDB:\n{item}\n")
78
75
 
@@ -106,9 +103,9 @@ class DashdotdbSLO(DashdotdbBase):
106
103
  continue
107
104
 
108
105
  ns = namespace_access.namespace
109
- promtoken: Optional[str] = None
110
- username: Optional[str] = None
111
- password: Optional[str] = None
106
+ promtoken: str | None = None
107
+ username: str | None = None
108
+ password: str | None = None
112
109
  if namespace_access.prometheus_access:
113
110
  promurl = namespace_access.prometheus_access.url
114
111
  username = self.secret_reader.read_secret(
@@ -1,5 +1,6 @@
1
1
  import base64
2
2
  import logging
3
+ from collections.abc import Callable
3
4
  from random import choices
4
5
  from string import (
5
6
  ascii_letters,
@@ -7,8 +8,6 @@ from string import (
7
8
  )
8
9
  from typing import (
9
10
  Any,
10
- Callable,
11
- Optional,
12
11
  TypedDict,
13
12
  cast,
14
13
  )
@@ -57,7 +56,7 @@ JOB_PSQL_ENGINE_VERSION = "15.4-alpine"
57
56
 
58
57
 
59
58
  def get_database_access_namespaces(
60
- query_func: Optional[Callable] = None,
59
+ query_func: Callable | None = None,
61
60
  ) -> list[NamespaceV1]:
62
61
  if not query_func:
63
62
  query_func = gql.get_api().query
@@ -74,7 +73,7 @@ class DatabaseConnectionParameters(BaseModel):
74
73
 
75
74
  class PSQLScriptGenerator(BaseModel):
76
75
  db_access: DatabaseAccessV1
77
- current_db_access: Optional[DatabaseAccessV1]
76
+ current_db_access: DatabaseAccessV1 | None
78
77
  connection_parameter: DatabaseConnectionParameters
79
78
  admin_connection_parameter: DatabaseConnectionParameters
80
79
  engine: str
@@ -426,7 +425,7 @@ def _populate_resources(
426
425
  settings: dict[Any, Any],
427
426
  user_connection: DatabaseConnectionParameters,
428
427
  admin_connection: DatabaseConnectionParameters,
429
- current_db_access: Optional[DatabaseAccessV1] = None,
428
+ current_db_access: DatabaseAccessV1 | None = None,
430
429
  ) -> list[DBAMResource]:
431
430
  if user_connection.database == admin_connection.database:
432
431
  raise ValueError(f"Can not use default database {admin_connection.database}")
@@ -594,7 +593,7 @@ def _process_db_access(
594
593
  if not _db_access_acccess_is_valid(db_access):
595
594
  raise ValueError("Duplicate schema in access list.")
596
595
 
597
- current_db_access: Optional[DatabaseAccessV1] = None
596
+ current_db_access: DatabaseAccessV1 | None = None
598
597
  if state.exists(db_access.name):
599
598
  current_state = state.get(db_access.name)
600
599
  if current_state == db_access.dict(by_alias=True):
@@ -1,12 +1,9 @@
1
1
  import base64
2
2
  import logging
3
3
  import sys
4
- from collections.abc import Iterable
4
+ from collections.abc import Iterable, Mapping
5
5
  from datetime import timedelta
6
- from typing import (
7
- Any,
8
- Mapping,
9
- )
6
+ from typing import Any
10
7
 
11
8
  from dynatrace import Dynatrace
12
9
  from dynatrace.environment_v2.tokens_api import ApiTokenCreated
@@ -1,5 +1,5 @@
1
1
  import logging
2
- from typing import Callable
2
+ from collections.abc import Callable
3
3
 
4
4
  from reconcile.external_resources.manager import (
5
5
  ExternalResourcesInventory,
@@ -1,8 +1,8 @@
1
1
  import json
2
2
  import logging
3
3
  from collections.abc import Iterable
4
- from datetime import datetime, timezone
5
- from enum import Enum
4
+ from datetime import UTC, datetime
5
+ from enum import StrEnum
6
6
 
7
7
  from sretoolbox.utils import threaded
8
8
 
@@ -73,7 +73,7 @@ def setup_factories(
73
73
  return of
74
74
 
75
75
 
76
- class ReconcileAction(str, Enum):
76
+ class ReconcileAction(StrEnum):
77
77
  NOOP = "NOOP"
78
78
  APPLY_NOT_EXISTS = "Resource does not exist"
79
79
  APPLY_ERROR = "Resource status in ERROR state"
@@ -260,7 +260,7 @@ class ExternalResourcesManager:
260
260
  return need_secret_sync
261
261
 
262
262
  def _update_state(self, r: Reconciliation, state: ExternalResourceState) -> None:
263
- state.ts = datetime.now(timezone.utc)
263
+ state.ts = datetime.now(UTC)
264
264
  if r.action == Action.APPLY:
265
265
  state.resource_status = ResourceStatus.IN_PROGRESS
266
266
  elif r.action == Action.DESTROY:
@@ -9,7 +9,7 @@ from collections.abc import (
9
9
  Iterator,
10
10
  MutableMapping,
11
11
  )
12
- from enum import Enum
12
+ from enum import StrEnum
13
13
  from typing import Any
14
14
 
15
15
  from pydantic import BaseModel
@@ -82,7 +82,7 @@ class ExternalResourcesInventory(MutableMapping):
82
82
  for (p, ns) in desired_providers
83
83
  for r in p.resources
84
84
  if isinstance(
85
- r, (NamespaceTerraformResourceRDSV1, NamespaceTerraformResourceRoleV1)
85
+ r, NamespaceTerraformResourceRDSV1 | NamespaceTerraformResourceRoleV1
86
86
  )
87
87
  and r.managed_by_erv2
88
88
  ]
@@ -123,7 +123,7 @@ class ExternalResourcesInventory(MutableMapping):
123
123
  raise FetchResourceError(msg)
124
124
 
125
125
 
126
- class Action(str, Enum):
126
+ class Action(StrEnum):
127
127
  DESTROY: str = "Destroy"
128
128
  APPLY: str = "Apply"
129
129
 
@@ -3,9 +3,9 @@ import json
3
3
  import logging
4
4
  from abc import abstractmethod
5
5
  from collections.abc import Iterable, Mapping
6
- from datetime import datetime, timezone
6
+ from datetime import UTC, datetime
7
7
  from hashlib import shake_128
8
- from typing import Any, Optional
8
+ from typing import Any
9
9
 
10
10
  from pydantic import BaseModel
11
11
  from sretoolbox.utils import threaded
@@ -45,8 +45,8 @@ class VaultSecret(BaseModel):
45
45
 
46
46
  path: str
47
47
  field: str
48
- version: Optional[int]
49
- q_format: Optional[str]
48
+ version: int | None
49
+ q_format: str | None
50
50
 
51
51
 
52
52
  class SecretHelper:
@@ -324,7 +324,7 @@ class InClusterSecretsReconciler(SecretsReconciler):
324
324
  else:
325
325
  data[k] = decoded
326
326
 
327
- spec.metadata[SECRET_UPDATED_AT] = datetime.now(timezone.utc).strftime(
327
+ spec.metadata[SECRET_UPDATED_AT] = datetime.now(UTC).strftime(
328
328
  SECRET_UPDATED_AT_TIMEFORMAT
329
329
  )
330
330
  spec.secret = data
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  from collections.abc import Mapping
3
- from datetime import datetime, timezone
4
- from enum import Enum
3
+ from datetime import UTC, datetime
4
+ from enum import StrEnum
5
5
  from typing import Any
6
6
 
7
7
  from pydantic import BaseModel
@@ -20,14 +20,14 @@ class StateNotFoundError(Exception):
20
20
  pass
21
21
 
22
22
 
23
- class ReconcileStatus(str, Enum):
23
+ class ReconcileStatus(StrEnum):
24
24
  SUCCESS: str = "SUCCESS"
25
25
  ERROR: str = "ERROR"
26
26
  IN_PROGRESS: str = "IN_PROGRESS"
27
27
  NOT_EXISTS: str = "NOT_EXISTS"
28
28
 
29
29
 
30
- class ResourceStatus(str, Enum):
30
+ class ResourceStatus(StrEnum):
31
31
  CREATED: str = "CREATED"
32
32
  DELETED: str = "DELETED"
33
33
  ABANDONED: str = "ABANDONED"
@@ -198,7 +198,7 @@ class ExternalResourcesStateDynamoDB:
198
198
  else:
199
199
  return ExternalResourceState(
200
200
  key=key,
201
- ts=datetime.now(timezone.utc),
201
+ ts=datetime.now(UTC),
202
202
  resource_status=ResourceStatus.NOT_EXISTS,
203
203
  reconciliation=Reconciliation(key=key),
204
204
  reconciliation_errors=0,
@@ -10,10 +10,7 @@ from datetime import (
10
10
  date,
11
11
  datetime,
12
12
  )
13
- from typing import (
14
- Any,
15
- Optional,
16
- )
13
+ from typing import Any
17
14
 
18
15
  import reconcile.openshift_base as ob
19
16
  from reconcile import queries
@@ -114,9 +111,9 @@ def fetch_desired_state(
114
111
  def run(
115
112
  dry_run: bool,
116
113
  thread_pool_size: int = 10,
117
- internal: Optional[bool] = None,
114
+ internal: bool | None = None,
118
115
  use_jump_host: bool = True,
119
- defer: Optional[Callable] = None,
116
+ defer: Callable | None = None,
120
117
  ) -> None:
121
118
  gabi_instances = queries.get_gabi_instances()
122
119
  if not gabi_instances:
reconcile/gcr_mirror.py CHANGED
@@ -241,7 +241,7 @@ class QuayMirror:
241
241
  control_file_name = "qontract-reconcile-gcr-mirror.timestamp"
242
242
  control_file_path = os.path.join(tempfile.gettempdir(), control_file_name)
243
243
  try:
244
- with open(control_file_path, "r", encoding="locale") as file_obj:
244
+ with open(control_file_path, encoding="locale") as file_obj:
245
245
  last_deep_sync = float(file_obj.read())
246
246
  except FileNotFoundError:
247
247
  self._record_timestamp(control_file_path)
reconcile/github_org.py CHANGED
@@ -438,9 +438,7 @@ def run(dry_run):
438
438
 
439
439
  assert (
440
440
  current_orgs == desired_orgs
441
- ), "Current orgs ({}) don't match desired orgs ({})".format(
442
- current_orgs, desired_orgs
443
- )
441
+ ), f"Current orgs ({current_orgs}) don't match desired orgs ({desired_orgs})"
444
442
 
445
443
  # Calculate diff
446
444
  diff = current_state.diff(desired_state)
@@ -5,10 +5,7 @@ from collections.abc import (
5
5
  Mapping,
6
6
  )
7
7
  from dataclasses import dataclass
8
- from typing import (
9
- Any,
10
- Optional,
11
- )
8
+ from typing import Any
12
9
 
13
10
  from reconcile import queries
14
11
  from reconcile.utils import (
@@ -27,7 +24,7 @@ class CodeComponents:
27
24
 
28
25
 
29
26
  def _parse_code_components(
30
- raw: Optional[Iterable[Mapping[str, Any]]],
27
+ raw: Iterable[Mapping[str, Any]] | None,
31
28
  ) -> CodeComponents:
32
29
  urls = set()
33
30
  known_orgs = set()
@@ -9,11 +9,7 @@ from datetime import (
9
9
  timedelta,
10
10
  )
11
11
  from operator import itemgetter
12
- from typing import (
13
- Any,
14
- Optional,
15
- Union,
16
- )
12
+ from typing import Any
17
13
 
18
14
  import gitlab
19
15
  from gitlab.v4.objects import (
@@ -178,7 +174,7 @@ def close_item(
178
174
  gl: GitLabApi,
179
175
  enable_closing: bool,
180
176
  item_type: str,
181
- item: Union[ProjectIssue, ProjectMergeRequest],
177
+ item: ProjectIssue | ProjectMergeRequest,
182
178
  ):
183
179
  if enable_closing:
184
180
  logging.info([
@@ -239,7 +235,7 @@ def handle_stale_items(
239
235
  cancel_notes = [
240
236
  n
241
237
  for n in item.notes.list()
242
- if n.attributes.get("body") == "/{} cancel".format(LABEL)
238
+ if n.attributes.get("body") == f"/{LABEL} cancel"
243
239
  ]
244
240
  if not cancel_notes:
245
241
  continue
@@ -280,7 +276,7 @@ def is_rebased(mr, gl: GitLabApi) -> bool:
280
276
  def get_merge_requests(
281
277
  dry_run: bool,
282
278
  gl: GitLabApi,
283
- users_allowed_to_label: Optional[Iterable[str]] = None,
279
+ users_allowed_to_label: Iterable[str] | None = None,
284
280
  ) -> list[dict[str, Any]]:
285
281
  mrs = gl.get_merge_requests(state=MRState.OPENED)
286
282
  return preprocess_merge_requests(
@@ -295,7 +291,7 @@ def preprocess_merge_requests(
295
291
  dry_run: bool,
296
292
  gl: GitLabApi,
297
293
  project_merge_requests: list[ProjectMergeRequest],
298
- users_allowed_to_label: Optional[Iterable[str]] = None,
294
+ users_allowed_to_label: Iterable[str] | None = None,
299
295
  ) -> list[dict[str, Any]]:
300
296
  results = []
301
297
  for mr in project_merge_requests:
@@ -434,7 +430,7 @@ def rebase_merge_requests(
434
430
  rebases += 1
435
431
  rebased_merge_requests.labels(mr.target_project_id).inc()
436
432
  except gitlab.exceptions.GitlabMRRebaseError as e:
437
- logging.error("unable to rebase {}: {}".format(mr.iid, e))
433
+ logging.error(f"unable to rebase {mr.iid}: {e}")
438
434
  else:
439
435
  logging.info([
440
436
  "rebase",
@@ -538,7 +534,7 @@ def merge_merge_requests(
538
534
  return
539
535
  merges += 1
540
536
  except gitlab.exceptions.GitlabMRClosedError as e:
541
- logging.error("unable to merge {}: {}".format(mr.iid, e))
537
+ logging.error(f"unable to merge {mr.iid}: {e}")
542
538
 
543
539
 
544
540
  def get_app_sre_usernames(gl: GitLabApi) -> set[str]:
@@ -4,7 +4,6 @@ from collections.abc import (
4
4
  Iterable,
5
5
  Set,
6
6
  )
7
- from typing import Optional
8
7
 
9
8
  from reconcile import queries
10
9
  from reconcile.gitlab_housekeeping import (
@@ -48,7 +47,7 @@ def get_parents_list() -> set[str]:
48
47
 
49
48
  def guess_onboarding_status(
50
49
  changed_paths: Iterable[str], apps: dict[str, dict], parent_apps: set[str]
51
- ) -> Optional[str]:
50
+ ) -> str | None:
52
51
  """
53
52
  Guess the service name of a given MR from the changed paths of the
54
53
  MR. This will allow to add the onboarding status to the MR's as label
@@ -1,10 +1,7 @@
1
1
  import enum
2
2
  import logging
3
3
  from collections.abc import Callable
4
- from typing import (
5
- Any,
6
- Optional,
7
- )
4
+ from typing import Any
8
5
 
9
6
  from pydantic import BaseModel
10
7
 
@@ -203,7 +200,7 @@ def get_gitlab_instance(query_func: Callable) -> GitlabInstanceV1:
203
200
  @defer
204
201
  def run(
205
202
  dry_run: bool,
206
- defer: Optional[Callable] = None,
203
+ defer: Callable | None = None,
207
204
  ) -> None:
208
205
  gqlapi = gql.get_api()
209
206
  # queries
@@ -21,9 +21,7 @@ def get_members_to_add(repo, gl, app_sre):
21
21
  if maintainers is None:
22
22
  return []
23
23
  if gl.user.username not in maintainers:
24
- logging.error(
25
- "'{}' is not shared with {} as 'Maintainer'".format(repo, gl.user.username)
26
- )
24
+ logging.error(f"'{repo}' is not shared with {gl.user.username} as 'Maintainer'")
27
25
  return []
28
26
  members_to_add = [
29
27
  {"user": u, "repo": repo} for u in app_sre if u.username not in maintainers
@@ -3,10 +3,7 @@ from collections.abc import (
3
3
  Iterable,
4
4
  Sequence,
5
5
  )
6
- from typing import (
7
- Any,
8
- Optional,
9
- )
6
+ from typing import Any
10
7
 
11
8
  from reconcile.glitchtip.reconciler import GlitchtipReconciler
12
9
  from reconcile.gql_definitions.glitchtip.glitchtip_instance import (
@@ -172,7 +169,7 @@ def get_internal_groups_client(
172
169
 
173
170
  @defer
174
171
  def run(
175
- dry_run: bool, instance: Optional[str] = None, defer: Optional[Callable] = None
172
+ dry_run: bool, instance: str | None = None, defer: Callable | None = None
176
173
  ) -> None:
177
174
  gqlapi = gql.get_api()
178
175
  vault_settings = get_app_interface_vault_settings()