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
@@ -1,13 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Sequence
3
+ from collections.abc import Mapping, Sequence, Set
4
4
  from typing import (
5
- AbstractSet,
6
5
  Any,
7
- Mapping,
8
- Optional,
9
6
  Protocol,
10
- Union,
11
7
  runtime_checkable,
12
8
  )
13
9
 
@@ -17,7 +13,7 @@ from reconcile.utils.secret_reader import HasSecret
17
13
 
18
14
  @runtime_checkable
19
15
  class HasParameters(Protocol):
20
- parameters: Optional[dict[str, Any]]
16
+ parameters: dict[str, Any] | None
21
17
 
22
18
 
23
19
  class SaasFileSecretParameters(Protocol):
@@ -30,14 +26,14 @@ class SaasFileSecretParameters(Protocol):
30
26
  self,
31
27
  *,
32
28
  by_alias: bool = False,
33
- include: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None,
29
+ include: AbstractSetIntStr | MappingIntStrAny | None = None,
34
30
  ) -> dict[str, Any]: ...
35
31
 
36
32
 
37
- SaasSecretParameters = Optional[Sequence[SaasFileSecretParameters]]
33
+ SaasSecretParameters = Sequence[SaasFileSecretParameters] | None
38
34
  # Taken from pydantic.typing
39
- AbstractSetIntStr = AbstractSet[Union[int, str]]
40
- MappingIntStrAny = Mapping[Union[int, str], Any]
35
+ AbstractSetIntStr = Set[int | str]
36
+ MappingIntStrAny = Mapping[int | str, Any]
41
37
 
42
38
 
43
39
  @runtime_checkable
@@ -55,16 +51,16 @@ class SaasApp(Protocol):
55
51
  name: str
56
52
 
57
53
  @property
58
- def parent_app(self) -> Optional[SaasParentApp]: ...
54
+ def parent_app(self) -> SaasParentApp | None: ...
59
55
 
60
56
  @property
61
- def self_service_roles(self) -> Optional[Sequence[SaasRole]]: ...
57
+ def self_service_roles(self) -> Sequence[SaasRole] | None: ...
62
58
 
63
59
  @property
64
- def service_owners(self) -> Optional[Sequence[SaasServiceOwner]]: ...
60
+ def service_owners(self) -> Sequence[SaasServiceOwner] | None: ...
65
61
 
66
62
  @property
67
- def code_components(self) -> Optional[Sequence[AppCodeComponent]]: ...
63
+ def code_components(self) -> Sequence[AppCodeComponent] | None: ...
68
64
 
69
65
 
70
66
  class SaasPipelinesProvider(Protocol):
@@ -126,7 +122,7 @@ class SaasPipelinesProviderTekton(Protocol):
126
122
  @property
127
123
  def pipeline_templates(
128
124
  self,
129
- ) -> Optional[SaasPipelinesProviderTekton_PipelinesProviderPipelineTemplates]: ...
125
+ ) -> SaasPipelinesProviderTekton_PipelinesProviderPipelineTemplates | None: ...
130
126
 
131
127
 
132
128
  class SaasResourceRequestsRequirements(Protocol):
@@ -135,7 +131,7 @@ class SaasResourceRequestsRequirements(Protocol):
135
131
 
136
132
 
137
133
  class SaasResourceLimitsRequirements(Protocol):
138
- cpu: Optional[str]
134
+ cpu: str | None
139
135
  memory: str
140
136
 
141
137
 
@@ -161,30 +157,30 @@ class SaasSlackWorkspace(Protocol):
161
157
  name: str
162
158
 
163
159
  @property
164
- def integrations(self) -> Optional[Sequence[SaasSlackWorkspaceIntegration]]: ...
160
+ def integrations(self) -> Sequence[SaasSlackWorkspaceIntegration] | None: ...
165
161
 
166
162
 
167
163
  class SaasSlackOutputNotifications(Protocol):
168
- start: Optional[bool]
164
+ start: bool | None
169
165
 
170
166
 
171
167
  class SaasSlackOutput(Protocol):
172
- output: Optional[str]
173
- channel: Optional[str]
168
+ output: str | None
169
+ channel: str | None
174
170
 
175
171
  @property
176
172
  def workspace(self) -> SaasSlackWorkspace: ...
177
173
 
178
174
  @property
179
- def notifications(self) -> Optional[SaasSlackOutputNotifications]: ...
175
+ def notifications(self) -> SaasSlackOutputNotifications | None: ...
180
176
 
181
177
 
182
178
  class SaasFileAuthentication(Protocol):
183
179
  @property
184
- def code(self) -> Optional[HasSecret]: ...
180
+ def code(self) -> HasSecret | None: ...
185
181
 
186
182
  @property
187
- def image(self) -> Optional[HasSecret]: ...
183
+ def image(self) -> HasSecret | None: ...
188
184
 
189
185
 
190
186
  class SaasEnvironment_SaasSecretParameters(Protocol):
@@ -215,7 +211,7 @@ class SaasResourceTemplateTargetNamespace(Protocol):
215
211
  self,
216
212
  *,
217
213
  by_alias: bool = False,
218
- include: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None,
214
+ include: AbstractSetIntStr | MappingIntStrAny | None = None,
219
215
  ) -> dict[str, Any]: ...
220
216
 
221
217
 
@@ -226,29 +222,27 @@ class SaasPromotionChannelData(Protocol):
226
222
  @runtime_checkable
227
223
  class SaasParentSaasPromotion(Protocol):
228
224
  q_type: str
229
- parent_saas: Optional[str]
230
- target_config_hash: Optional[str]
225
+ parent_saas: str | None
226
+ target_config_hash: str | None
231
227
 
232
228
 
233
229
  class SaasPromotionData(Protocol):
234
- channel: Optional[str]
230
+ channel: str | None
235
231
 
236
232
  @property
237
233
  def data(
238
234
  self,
239
- ) -> Optional[
240
- Sequence[Union[SaasParentSaasPromotion, SaasPromotionChannelData]]
241
- ]: ...
235
+ ) -> Sequence[SaasParentSaasPromotion | SaasPromotionChannelData] | None: ...
242
236
 
243
237
 
244
238
  class SaasResourceTemplateTargetPromotion(Protocol):
245
- auto: Optional[bool]
246
- publish: Optional[list[str]]
247
- subscribe: Optional[list[str]]
248
- soak_days: Optional[int]
239
+ auto: bool | None
240
+ publish: list[str] | None
241
+ subscribe: list[str] | None
242
+ soak_days: int | None
249
243
 
250
244
  @property
251
- def promotion_data(self) -> Optional[Sequence[SaasPromotionData]]: ...
245
+ def promotion_data(self) -> Sequence[SaasPromotionData] | None: ...
252
246
 
253
247
 
254
248
  class Channel(Protocol):
@@ -261,17 +255,17 @@ class SaasPromotion(Protocol):
261
255
  commit_sha: str
262
256
  saas_file: str
263
257
  target_config_hash: str
264
- auto: Optional[bool] = None
265
- publish: Optional[list[str]] = None
266
- saas_file_paths: Optional[list[str]] = None
267
- target_paths: Optional[list[str]] = None
268
- soak_days: Optional[int] = None
258
+ auto: bool | None = None
259
+ publish: list[str] | None = None
260
+ saas_file_paths: list[str] | None = None
261
+ target_paths: list[str] | None = None
262
+ soak_days: int | None = None
269
263
 
270
264
  @property
271
- def promotion_data(self) -> Optional[Sequence[SaasPromotionData]]: ...
265
+ def promotion_data(self) -> Sequence[SaasPromotionData] | None: ...
272
266
 
273
267
  @property
274
- def subscribe(self) -> Optional[list[Channel]]: ...
268
+ def subscribe(self) -> list[Channel] | None: ...
275
269
 
276
270
  def dict(self, *, by_alias: bool = False) -> dict[str, Any]: ...
277
271
 
@@ -314,23 +308,23 @@ class SaasResourceTemplateTargetImage(Protocol):
314
308
 
315
309
 
316
310
  class SaasResourceTemplateTarget(HasParameters, HasSecretParameters, Protocol):
317
- path: Optional[str]
318
- name: Optional[str]
319
- disable: Optional[bool]
320
- delete: Optional[bool]
311
+ path: str | None
312
+ name: str | None
313
+ disable: bool | None
314
+ delete: bool | None
321
315
  ref: str
322
316
 
323
317
  @property
324
318
  def namespace(self) -> SaasResourceTemplateTargetNamespace: ...
325
319
 
326
320
  @property
327
- def promotion(self) -> Optional[SaasResourceTemplateTargetPromotion]: ...
321
+ def promotion(self) -> SaasResourceTemplateTargetPromotion | None: ...
328
322
 
329
323
  @property
330
- def upstream(self) -> Optional[SaasResourceTemplateTargetUpstream]: ...
324
+ def upstream(self) -> SaasResourceTemplateTargetUpstream | None: ...
331
325
 
332
326
  @property
333
- def image(self) -> Optional[SaasResourceTemplateTargetImage]: ...
327
+ def image(self) -> SaasResourceTemplateTargetImage | None: ...
334
328
 
335
329
  def uid(
336
330
  self, parent_saas_file_name: str, parent_resource_template_name: str
@@ -343,8 +337,8 @@ class SaasResourceTemplate(HasParameters, HasSecretParameters, Protocol):
343
337
  name: str
344
338
  url: str
345
339
  path: str
346
- provider: Optional[str]
347
- hash_length: Optional[int]
340
+ provider: str | None
341
+ hash_length: int | None
348
342
 
349
343
  @property
350
344
  def targets(self) -> Sequence[SaasResourceTemplateTarget]: ...
@@ -361,11 +355,11 @@ class SaasServiceOwner(Protocol):
361
355
 
362
356
  class AppCodeComponent(Protocol):
363
357
  url: str
364
- blocked_versions: Optional[list[str]]
365
- hotfix_versions: Optional[list[str]]
358
+ blocked_versions: list[str] | None
359
+ hotfix_versions: list[str] | None
366
360
 
367
361
 
368
- SaasPipelinesProviders = Union[SaasPipelinesProviderTekton, SaasPipelinesProvider]
362
+ SaasPipelinesProviders = SaasPipelinesProviderTekton | SaasPipelinesProvider
369
363
 
370
364
 
371
365
  @runtime_checkable
@@ -377,18 +371,18 @@ class ManagedResourceName(Protocol):
377
371
  class SaasFile(HasParameters, HasSecretParameters, Protocol):
378
372
  path: str
379
373
  name: str
380
- labels: Optional[dict[str, Any]]
374
+ labels: dict[str, Any] | None
381
375
  managed_resource_types: list[str]
382
- takeover: Optional[bool]
383
- deprecated: Optional[bool]
384
- compare: Optional[bool]
385
- timeout: Optional[str]
386
- publish_job_logs: Optional[bool]
387
- cluster_admin: Optional[bool]
376
+ takeover: bool | None
377
+ deprecated: bool | None
378
+ compare: bool | None
379
+ timeout: str | None
380
+ publish_job_logs: bool | None
381
+ cluster_admin: bool | None
388
382
  image_patterns: list[str]
389
- allowed_secret_parameter_paths: Optional[list[str]]
390
- use_channel_in_image_tag: Optional[bool]
391
- validate_targets_in_app: Optional[bool]
383
+ allowed_secret_parameter_paths: list[str] | None
384
+ use_channel_in_image_tag: bool | None
385
+ validate_targets_in_app: bool | None
392
386
 
393
387
  @property
394
388
  def app(self) -> SaasApp: ...
@@ -397,19 +391,19 @@ class SaasFile(HasParameters, HasSecretParameters, Protocol):
397
391
  def pipelines_provider(self) -> SaasPipelinesProviders: ...
398
392
 
399
393
  @property
400
- def deploy_resources(self) -> Optional[SaasDeployResources]: ...
394
+ def deploy_resources(self) -> SaasDeployResources | None: ...
401
395
 
402
396
  @property
403
- def slack(self) -> Optional[SaasSlackOutput]: ...
397
+ def slack(self) -> SaasSlackOutput | None: ...
404
398
 
405
399
  @property
406
- def authentication(self) -> Optional[SaasFileAuthentication]: ...
400
+ def authentication(self) -> SaasFileAuthentication | None: ...
407
401
 
408
402
  @property
409
403
  def resource_templates(self) -> Sequence[SaasResourceTemplate]: ...
410
404
 
411
405
  @property
412
- def self_service_roles(self) -> Optional[Sequence[SaasRole]]: ...
406
+ def self_service_roles(self) -> Sequence[SaasRole] | None: ...
413
407
 
414
408
  @property
415
- def managed_resource_names(self) -> Optional[Sequence[ManagedResourceName]]: ...
409
+ def managed_resource_names(self) -> Sequence[ManagedResourceName] | None: ...
@@ -1,13 +1,8 @@
1
1
  import base64
2
- from collections.abc import Iterable
2
+ from collections.abc import Iterable, Sequence
3
3
  from dataclasses import dataclass
4
4
  from enum import Enum
5
- from typing import (
6
- Any,
7
- Optional,
8
- Sequence,
9
- Union,
10
- )
5
+ from typing import Any
11
6
 
12
7
  from github import Github
13
8
  from pydantic import (
@@ -52,7 +47,7 @@ class UpstreamJob:
52
47
  class TriggerSpecBase:
53
48
  saas_file_name: str
54
49
  env_name: str
55
- timeout: Optional[str]
50
+ timeout: str | None
56
51
  pipelines_provider: SaasPipelinesProviders
57
52
  resource_template_name: str
58
53
  cluster_name: str
@@ -66,8 +61,8 @@ class TriggerSpecBase:
66
61
 
67
62
  @dataclass
68
63
  class TriggerSpecConfig(TriggerSpecBase):
69
- target_name: Optional[str] = None
70
- reason: Optional[str] = None
64
+ target_name: str | None = None
65
+ reason: str | None = None
71
66
 
72
67
  @property
73
68
  def state_key(self) -> str:
@@ -83,7 +78,7 @@ class TriggerSpecConfig(TriggerSpecBase):
83
78
  @dataclass
84
79
  class TriggerSpecMovingCommit(TriggerSpecBase):
85
80
  ref: str
86
- reason: Optional[str] = None
81
+ reason: str | None = None
87
82
 
88
83
  @property
89
84
  def state_key(self) -> str:
@@ -98,7 +93,7 @@ class TriggerSpecMovingCommit(TriggerSpecBase):
98
93
  class TriggerSpecUpstreamJob(TriggerSpecBase):
99
94
  instance_name: str
100
95
  job_name: str
101
- reason: Optional[str] = None
96
+ reason: str | None = None
102
97
 
103
98
  @property
104
99
  def state_key(self) -> str:
@@ -112,7 +107,7 @@ class TriggerSpecUpstreamJob(TriggerSpecBase):
112
107
  @dataclass
113
108
  class TriggerSpecContainerImage(TriggerSpecBase):
114
109
  image: str
115
- reason: Optional[str] = None
110
+ reason: str | None = None
116
111
 
117
112
  @property
118
113
  def state_key(self) -> str:
@@ -123,12 +118,12 @@ class TriggerSpecContainerImage(TriggerSpecBase):
123
118
  return key
124
119
 
125
120
 
126
- TriggerSpecUnion = Union[
127
- TriggerSpecConfig,
128
- TriggerSpecMovingCommit,
129
- TriggerSpecUpstreamJob,
130
- TriggerSpecContainerImage,
131
- ]
121
+ TriggerSpecUnion = (
122
+ TriggerSpecConfig
123
+ | TriggerSpecMovingCommit
124
+ | TriggerSpecUpstreamJob
125
+ | TriggerSpecContainerImage
126
+ )
132
127
 
133
128
 
134
129
  class Namespace(BaseModel):
@@ -137,7 +132,7 @@ class Namespace(BaseModel):
137
132
  app: SaasApp
138
133
  cluster: Cluster
139
134
  managed_resource_types: list[str] = Field(..., alias="managedResourceTypes")
140
- managed_resource_names: Optional[Sequence[ManagedResourceName]] = Field(
135
+ managed_resource_names: Sequence[ManagedResourceName] | None = Field(
141
136
  ..., alias="managedResourceNames"
142
137
  )
143
138
 
@@ -155,16 +150,16 @@ class PromotionChannelData(BaseModel):
155
150
 
156
151
  class ParentSaasPromotion(BaseModel):
157
152
  q_type: str = Field(..., alias="type")
158
- parent_saas: Optional[str]
159
- target_config_hash: Optional[str]
153
+ parent_saas: str | None
154
+ target_config_hash: str | None
160
155
 
161
156
  class Config:
162
157
  allow_population_by_field_name = True
163
158
 
164
159
 
165
160
  class PromotionData(BaseModel):
166
- channel: Optional[str]
167
- data: Optional[list[Union[ParentSaasPromotion, PromotionChannelData]]] = None
161
+ channel: str | None
162
+ data: list[ParentSaasPromotion | PromotionChannelData] | None = None
168
163
 
169
164
 
170
165
  class Channel(BaseModel):
@@ -181,20 +176,20 @@ class Promotion(BaseModel):
181
176
  target_config_hash: str
182
177
  saas_target_uid: str
183
178
  soak_days: int
184
- auto: Optional[bool] = None
185
- publish: Optional[list[str]] = None
186
- subscribe: Optional[list[Channel]] = None
187
- promotion_data: Optional[list[PromotionData]] = None
188
- saas_file_paths: Optional[list[str]] = None
189
- target_paths: Optional[list[str]] = None
179
+ auto: bool | None = None
180
+ publish: list[str] | None = None
181
+ subscribe: list[Channel] | None = None
182
+ promotion_data: list[PromotionData] | None = None
183
+ saas_file_paths: list[str] | None = None
184
+ target_paths: list[str] | None = None
190
185
 
191
186
 
192
187
  @dataclass
193
188
  class ImageAuth:
194
- username: Optional[str] = None
195
- password: Optional[str] = None
196
- auth_server: Optional[str] = None
197
- docker_config: Optional[dict[str, dict[str, dict[str, str]]]] = None
189
+ username: str | None = None
190
+ password: str | None = None
191
+ auth_server: str | None = None
192
+ docker_config: dict[str, dict[str, dict[str, str]]] | None = None
198
193
 
199
194
  def getDockerConfigJson(self) -> dict:
200
195
  if self.docker_config:
@@ -219,7 +214,7 @@ class TargetSpec:
219
214
  cluster: str
220
215
  namespace: str
221
216
  managed_resource_types: Iterable[str]
222
- managed_resource_names: Optional[Sequence[ManagedResourceName]]
217
+ managed_resource_names: Sequence[ManagedResourceName] | None
223
218
  delete: bool
224
219
  privileged: bool
225
220
  image_auth: ImageAuth
@@ -10,22 +10,16 @@ from collections import (
10
10
  defaultdict,
11
11
  )
12
12
  from collections.abc import (
13
+ Generator,
13
14
  Iterable,
14
15
  Mapping,
15
16
  MutableMapping,
16
17
  Sequence,
17
18
  )
18
19
  from contextlib import suppress
19
- from datetime import datetime, timedelta, timezone
20
+ from datetime import UTC, datetime, timedelta
20
21
  from types import TracebackType
21
- from typing import (
22
- Any,
23
- Generator,
24
- Optional,
25
- Tuple,
26
- Type,
27
- Union,
28
- )
22
+ from typing import Any
29
23
  from urllib.parse import urlparse
30
24
 
31
25
  import yaml
@@ -121,12 +115,12 @@ class SaasHerder: # pylint: disable=too-many-public-methods
121
115
  secret_reader: SecretReaderBase,
122
116
  hash_length: int,
123
117
  repo_url: str,
124
- gitlab: Optional[GitLabApi] = None,
125
- jenkins_map: Optional[dict[str, JenkinsApi]] = None,
126
- state: Optional[State] = None,
118
+ gitlab: GitLabApi | None = None,
119
+ jenkins_map: dict[str, JenkinsApi] | None = None,
120
+ state: State | None = None,
127
121
  validate: bool = False,
128
122
  include_trigger_trace: bool = False,
129
- all_saas_files: Optional[Iterable[SaasFile]] = None,
123
+ all_saas_files: Iterable[SaasFile] | None = None,
130
124
  ):
131
125
  self.error_registered = False
132
126
  self.saas_files = saas_files
@@ -171,9 +165,9 @@ class SaasHerder: # pylint: disable=too-many-public-methods
171
165
 
172
166
  def __exit__(
173
167
  self,
174
- exc_type: Optional[Type[BaseException]],
175
- exc_value: Optional[BaseException],
176
- traceback: Optional[TracebackType],
168
+ exc_type: type[BaseException] | None,
169
+ exc_value: BaseException | None,
170
+ traceback: TracebackType | None,
177
171
  ) -> None:
178
172
  self.cleanup()
179
173
 
@@ -203,8 +197,8 @@ class SaasHerder: # pylint: disable=too-many-public-methods
203
197
  yield (saas_file, resource_template, target)
204
198
 
205
199
  def _get_saas_file_feature_enabled(
206
- self, name: str, default: Optional[bool] = None
207
- ) -> Optional[bool]:
200
+ self, name: str, default: bool | None = None
201
+ ) -> bool | None:
208
202
  """Returns a bool indicating if a feature is enabled in a saas file,
209
203
  or a supplied default. Returns False if there are multiple
210
204
  saas files in the process.
@@ -434,9 +428,8 @@ class SaasHerder: # pylint: disable=too-many-public-methods
434
428
  self.valid = False
435
429
  # This should never be possible theoretically ...
436
430
  logging.error(
437
- "Non-unique resource template reference {} in " "channel {}".format(
438
- rt_ref, channel
439
- )
431
+ f"Non-unique resource template reference {rt_ref} in "
432
+ f"channel {channel}"
440
433
  )
441
434
  continue
442
435
  publications[channel].add(rt_ref)
@@ -461,9 +454,9 @@ class SaasHerder: # pylint: disable=too-many-public-methods
461
454
  self.valid = False
462
455
  logging.error(
463
456
  "Channel is not published by any target\n"
464
- "subscriber_saas: {}\n"
465
- "subscriber_rt: {}\n"
466
- "channel: {}".format(sub_saas, sub_rt_name, sub_channel)
457
+ f"subscriber_saas: {sub_saas}\n"
458
+ f"subscriber_rt: {sub_rt_name}\n"
459
+ f"channel: {sub_channel}"
467
460
  )
468
461
  for pub_ref in pub_channel_refs:
469
462
  (pub_saas, pub_rt_name, pub_rt_url, _) = pub_ref
@@ -472,26 +465,19 @@ class SaasHerder: # pylint: disable=too-many-public-methods
472
465
  logging.error(
473
466
  "Subscriber and Publisher targets have different "
474
467
  "source repositories\n"
475
- "publisher_saas: {}\n"
476
- "publisher_rt: {}\n"
477
- "publisher_repo: {}\n"
478
- "subscriber_saas: {}\n"
479
- "subscriber_rt: {}\n"
480
- "subscriber_repo: {}\n".format(
481
- pub_saas,
482
- pub_rt_name,
483
- pub_rt_url,
484
- sub_saas,
485
- sub_rt_name,
486
- sub_rt_url,
487
- )
468
+ f"publisher_saas: {pub_saas}\n"
469
+ f"publisher_rt: {pub_rt_name}\n"
470
+ f"publisher_repo: {pub_rt_url}\n"
471
+ f"subscriber_saas: {sub_saas}\n"
472
+ f"subscriber_rt: {sub_rt_name}\n"
473
+ f"subscriber_repo: {sub_rt_url}\n"
488
474
  )
489
475
 
490
476
  @staticmethod
491
477
  def build_saas_file_env_combo(
492
478
  saas_file_name: str,
493
479
  env_name: str,
494
- ) -> Tuple[str, str]:
480
+ ) -> tuple[str, str]:
495
481
  """
496
482
  Build a tuple of short and long names for a saas file and environment combo,
497
483
  max tekton pipelinerun name length can be 63,
@@ -903,7 +889,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
903
889
 
904
890
  def _process_template(
905
891
  self, spec: TargetSpec
906
- ) -> tuple[list[Any], str, Optional[Promotion]]:
892
+ ) -> tuple[list[Any], str, Promotion | None]:
907
893
  saas_file_name = spec.saas_file_name
908
894
  resource_template_name = spec.resource_template_name
909
895
  image_auth = spec.image_auth
@@ -1076,7 +1062,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1076
1062
  return resources, html_url, target_promotion
1077
1063
 
1078
1064
  def _assemble_channels(
1079
- self, saas_files: Optional[Iterable[SaasFile]]
1065
+ self, saas_files: Iterable[SaasFile] | None
1080
1066
  ) -> dict[str, Channel]:
1081
1067
  """
1082
1068
  We need to assemble all publisher_uids that are publishing to a channel.
@@ -1157,7 +1143,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1157
1143
  image_patterns: Iterable[str],
1158
1144
  image_auth: ImageAuth,
1159
1145
  error_prefix: str,
1160
- ) -> Optional[Image]:
1146
+ ) -> Image | None:
1161
1147
  if not image_patterns:
1162
1148
  logging.error(
1163
1149
  f"{error_prefix} imagePatterns is empty (does not contain {image})"
@@ -1230,7 +1216,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1230
1216
  return None in images
1231
1217
 
1232
1218
  def _initiate_github(
1233
- self, saas_file: SaasFile, base_url: Optional[str] = None
1219
+ self, saas_file: SaasFile, base_url: str | None = None
1234
1220
  ) -> Github:
1235
1221
  token = (
1236
1222
  self.secret_reader.read_secret(saas_file.authentication.code)
@@ -1293,7 +1279,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1293
1279
  self.thread_pool_size,
1294
1280
  ri=ri,
1295
1281
  )
1296
- self.promotions: list[Optional[Promotion]] = promotions
1282
+ self.promotions: list[Promotion | None] = promotions
1297
1283
 
1298
1284
  def _init_populate_desired_state_specs(
1299
1285
  self, saas_file: SaasFile
@@ -1368,7 +1354,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1368
1354
 
1369
1355
  def populate_desired_state_saas_file(
1370
1356
  self, spec: TargetSpec, ri: ResourceInventory
1371
- ) -> Optional[Promotion]:
1357
+ ) -> Promotion | None:
1372
1358
  if spec.delete:
1373
1359
  # to delete resources, we avoid adding them to the desired state
1374
1360
  return None
@@ -1460,12 +1446,10 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1460
1446
  def get_diff(
1461
1447
  self, trigger_type: TriggerTypes, dry_run: bool
1462
1448
  ) -> tuple[
1463
- Union[
1464
- list[TriggerSpecConfig],
1465
- list[TriggerSpecMovingCommit],
1466
- list[TriggerSpecUpstreamJob],
1467
- list[TriggerSpecContainerImage],
1468
- ],
1449
+ list[TriggerSpecConfig]
1450
+ | list[TriggerSpecMovingCommit]
1451
+ | list[TriggerSpecUpstreamJob]
1452
+ | list[TriggerSpecContainerImage],
1469
1453
  bool,
1470
1454
  ]:
1471
1455
  if trigger_type == TriggerTypes.MOVING_COMMITS:
@@ -1759,7 +1743,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1759
1743
  return list(itertools.chain.from_iterable(results))
1760
1744
 
1761
1745
  @staticmethod
1762
- def remove_none_values(d: Optional[dict[Any, Any]]) -> dict[Any, Any]:
1746
+ def remove_none_values(d: dict[Any, Any] | None) -> dict[Any, Any]:
1763
1747
  if d is None:
1764
1748
  return {}
1765
1749
  new = {}
@@ -1916,7 +1900,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1916
1900
  if promotion.commit_sha in self.hotfix_versions.get(promotion.url, set()):
1917
1901
  return True
1918
1902
 
1919
- now = datetime.now(timezone.utc)
1903
+ now = datetime.now(UTC)
1920
1904
  passed_soak_days = timedelta(days=0)
1921
1905
 
1922
1906
  for channel in promotion.subscribe:
@@ -2016,7 +2000,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
2016
2000
  if not (self.state and self._promotion_state):
2017
2001
  raise Exception("state is not initialized")
2018
2002
 
2019
- now = datetime.now(timezone.utc)
2003
+ now = datetime.now(UTC)
2020
2004
  for promotion in self.promotions:
2021
2005
  if promotion is None:
2022
2006
  continue