qontract-reconcile 0.10.2.dev394__py3-none-any.whl → 0.10.2.dev427__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 (316) hide show
  1. {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.dist-info}/METADATA +5 -4
  2. {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.dist-info}/RECORD +316 -315
  3. reconcile/acs_rbac.py +2 -2
  4. reconcile/aus/advanced_upgrade_service.py +18 -12
  5. reconcile/aus/base.py +117 -18
  6. reconcile/aus/cluster_version_data.py +15 -5
  7. reconcile/aus/models.py +3 -1
  8. reconcile/aus/ocm_addons_upgrade_scheduler_org.py +1 -0
  9. reconcile/aus/ocm_upgrade_scheduler.py +8 -1
  10. reconcile/aus/ocm_upgrade_scheduler_org.py +20 -5
  11. reconcile/aus/version_gates/sts_version_gate_handler.py +54 -1
  12. reconcile/automated_actions/config/integration.py +16 -4
  13. reconcile/aws_account_manager/integration.py +6 -6
  14. reconcile/aws_account_manager/reconciler.py +3 -3
  15. reconcile/aws_ami_cleanup/integration.py +2 -5
  16. reconcile/aws_ami_share.py +69 -62
  17. reconcile/aws_saml_idp/integration.py +5 -3
  18. reconcile/aws_saml_roles/integration.py +23 -22
  19. reconcile/aws_version_sync/integration.py +6 -12
  20. reconcile/change_owners/bundle.py +3 -3
  21. reconcile/change_owners/change_log_tracking.py +3 -2
  22. reconcile/change_owners/change_owners.py +1 -1
  23. reconcile/cli.py +62 -4
  24. reconcile/dashdotdb_dora.py +1 -1
  25. reconcile/dashdotdb_slo.py +1 -1
  26. reconcile/database_access_manager.py +8 -9
  27. reconcile/dynatrace_token_provider/integration.py +1 -1
  28. reconcile/endpoints_discovery/integration.py +4 -1
  29. reconcile/endpoints_discovery/merge_request.py +1 -1
  30. reconcile/endpoints_discovery/merge_request_manager.py +1 -1
  31. reconcile/external_resources/integration.py +1 -1
  32. reconcile/external_resources/manager.py +3 -2
  33. reconcile/external_resources/metrics.py +1 -1
  34. reconcile/external_resources/model.py +13 -13
  35. reconcile/external_resources/reconciler.py +7 -4
  36. reconcile/external_resources/secrets_sync.py +2 -2
  37. reconcile/external_resources/state.py +22 -13
  38. reconcile/fleet_labeler/integration.py +1 -1
  39. reconcile/gcp_image_mirror.py +2 -2
  40. reconcile/github_org.py +1 -1
  41. reconcile/github_owners.py +4 -0
  42. reconcile/gitlab_members.py +6 -12
  43. reconcile/gitlab_permissions.py +8 -12
  44. reconcile/glitchtip_project_alerts/integration.py +3 -1
  45. reconcile/gql_definitions/acs/acs_instances.py +5 -5
  46. reconcile/gql_definitions/acs/acs_policies.py +5 -5
  47. reconcile/gql_definitions/acs/acs_rbac.py +5 -5
  48. reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +5 -5
  49. reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +5 -5
  50. reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +5 -5
  51. reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
  52. reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
  53. reconcile/gql_definitions/automated_actions/instance.py +46 -7
  54. reconcile/gql_definitions/aws_account_manager/aws_accounts.py +5 -5
  55. reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +5 -5
  56. reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +5 -5
  57. reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +5 -5
  58. reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +5 -5
  59. reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
  60. reconcile/gql_definitions/aws_version_sync/clusters.py +5 -5
  61. reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
  62. reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
  63. reconcile/gql_definitions/change_owners/queries/self_service_roles.py +5 -5
  64. reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +5 -5
  65. reconcile/gql_definitions/common/alerting_services_settings.py +5 -5
  66. reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
  67. reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
  68. reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
  69. reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
  70. reconcile/gql_definitions/common/app_interface_roles.py +5 -5
  71. reconcile/gql_definitions/common/app_interface_state_settings.py +5 -5
  72. reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
  73. reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
  74. reconcile/gql_definitions/common/apps.py +5 -5
  75. reconcile/gql_definitions/common/aws_vpc_requests.py +5 -5
  76. reconcile/gql_definitions/common/aws_vpcs.py +5 -5
  77. reconcile/gql_definitions/common/clusters.py +5 -5
  78. reconcile/gql_definitions/common/clusters_minimal.py +5 -5
  79. reconcile/gql_definitions/common/clusters_with_dms.py +5 -5
  80. reconcile/gql_definitions/common/clusters_with_peering.py +5 -5
  81. reconcile/gql_definitions/common/github_orgs.py +5 -5
  82. reconcile/gql_definitions/common/jira_settings.py +5 -5
  83. reconcile/gql_definitions/common/jiralert_settings.py +5 -5
  84. reconcile/gql_definitions/common/ldap_settings.py +5 -5
  85. reconcile/gql_definitions/common/namespaces.py +5 -5
  86. reconcile/gql_definitions/common/namespaces_minimal.py +7 -5
  87. reconcile/gql_definitions/common/ocm_env_telemeter.py +5 -5
  88. reconcile/gql_definitions/common/ocm_environments.py +5 -5
  89. reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
  90. reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -5
  91. reconcile/gql_definitions/common/pipeline_providers.py +5 -5
  92. reconcile/gql_definitions/common/quay_instances.py +5 -5
  93. reconcile/gql_definitions/common/quay_orgs.py +5 -5
  94. reconcile/gql_definitions/common/reserved_networks.py +5 -5
  95. reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
  96. reconcile/gql_definitions/common/saas_files.py +5 -5
  97. reconcile/gql_definitions/common/saas_target_namespaces.py +5 -5
  98. reconcile/gql_definitions/common/saasherder_settings.py +5 -5
  99. reconcile/gql_definitions/common/slack_workspaces.py +5 -5
  100. reconcile/gql_definitions/common/smtp_client_settings.py +5 -5
  101. reconcile/gql_definitions/common/state_aws_account.py +5 -5
  102. reconcile/gql_definitions/common/users.py +5 -5
  103. reconcile/gql_definitions/common/users_with_paths.py +5 -5
  104. reconcile/gql_definitions/cost_report/app_names.py +5 -5
  105. reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
  106. reconcile/gql_definitions/cost_report/settings.py +5 -5
  107. reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +5 -5
  108. reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +5 -5
  109. reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
  110. reconcile/gql_definitions/email_sender/apps.py +5 -5
  111. reconcile/gql_definitions/email_sender/emails.py +5 -5
  112. reconcile/gql_definitions/email_sender/users.py +5 -5
  113. reconcile/gql_definitions/endpoints_discovery/apps.py +5 -5
  114. reconcile/gql_definitions/external_resources/aws_accounts.py +5 -5
  115. reconcile/gql_definitions/external_resources/external_resources_modules.py +5 -5
  116. reconcile/gql_definitions/external_resources/external_resources_namespaces.py +5 -5
  117. reconcile/gql_definitions/external_resources/external_resources_settings.py +5 -5
  118. reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
  119. reconcile/gql_definitions/fleet_labeler/fleet_labels.py +5 -5
  120. reconcile/gql_definitions/fragments/aus_organization.py +5 -5
  121. reconcile/gql_definitions/fragments/aws_account_common.py +5 -5
  122. reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
  123. reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
  124. reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
  125. reconcile/gql_definitions/fragments/aws_organization.py +5 -5
  126. reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
  127. reconcile/gql_definitions/fragments/aws_vpc_request.py +5 -5
  128. reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
  129. reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
  130. reconcile/gql_definitions/fragments/disable.py +5 -5
  131. reconcile/gql_definitions/fragments/email_service.py +5 -5
  132. reconcile/gql_definitions/fragments/email_user.py +5 -5
  133. reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
  134. reconcile/gql_definitions/fragments/membership_source.py +5 -5
  135. reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
  136. reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
  137. reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
  138. reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
  139. reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
  140. reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
  141. reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
  142. reconcile/gql_definitions/fragments/resource_values.py +5 -5
  143. reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
  144. reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
  145. reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
  146. reconcile/gql_definitions/fragments/terraform_state.py +5 -5
  147. reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
  148. reconcile/gql_definitions/fragments/user.py +5 -5
  149. reconcile/gql_definitions/fragments/vault_secret.py +5 -5
  150. reconcile/gql_definitions/gcp/gcp_docker_repos.py +5 -5
  151. reconcile/gql_definitions/gcp/gcp_projects.py +5 -5
  152. reconcile/gql_definitions/gitlab_members/gitlab_instances.py +5 -5
  153. reconcile/gql_definitions/gitlab_members/permissions.py +5 -5
  154. reconcile/gql_definitions/glitchtip/glitchtip_instance.py +5 -5
  155. reconcile/gql_definitions/glitchtip/glitchtip_project.py +5 -5
  156. reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +5 -5
  157. reconcile/gql_definitions/integrations/integrations.py +5 -5
  158. reconcile/gql_definitions/introspection.json +231 -0
  159. reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +5 -5
  160. reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +5 -5
  161. reconcile/gql_definitions/jira/jira_servers.py +5 -5
  162. reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +5 -5
  163. reconcile/gql_definitions/jumphosts/jumphosts.py +5 -5
  164. reconcile/gql_definitions/ldap_groups/roles.py +5 -5
  165. reconcile/gql_definitions/ldap_groups/settings.py +5 -5
  166. reconcile/gql_definitions/maintenance/maintenances.py +5 -5
  167. reconcile/gql_definitions/membershipsources/roles.py +5 -5
  168. reconcile/gql_definitions/ocm_labels/clusters.py +5 -5
  169. reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
  170. reconcile/gql_definitions/openshift_cluster_bots/clusters.py +5 -5
  171. reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
  172. reconcile/gql_definitions/openshift_groups/managed_roles.py +5 -5
  173. reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +5 -5
  174. reconcile/gql_definitions/quay_membership/quay_membership.py +5 -5
  175. reconcile/gql_definitions/rhcs/certs.py +24 -79
  176. reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +42 -0
  177. reconcile/gql_definitions/rhidp/organizations.py +5 -5
  178. reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
  179. reconcile/gql_definitions/service_dependencies/service_dependencies.py +5 -5
  180. reconcile/gql_definitions/sharding/aws_accounts.py +5 -5
  181. reconcile/gql_definitions/sharding/ocm_organization.py +5 -5
  182. reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
  183. reconcile/gql_definitions/skupper_network/skupper_networks.py +5 -5
  184. reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
  185. reconcile/gql_definitions/slack_usergroups/permissions.py +5 -5
  186. reconcile/gql_definitions/slack_usergroups/users.py +5 -5
  187. reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
  188. reconcile/gql_definitions/status_board/status_board.py +5 -5
  189. reconcile/gql_definitions/statuspage/statuspages.py +5 -5
  190. reconcile/gql_definitions/templating/template_collection.py +5 -5
  191. reconcile/gql_definitions/templating/templates.py +5 -5
  192. reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +5 -5
  193. reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +5 -5
  194. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +5 -5
  195. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +5 -5
  196. reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +5 -5
  197. reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +5 -5
  198. reconcile/gql_definitions/terraform_init/aws_accounts.py +5 -5
  199. reconcile/gql_definitions/terraform_repo/terraform_repo.py +5 -5
  200. reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
  201. reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +5 -5
  202. reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +5 -5
  203. reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +5 -5
  204. reconcile/gql_definitions/vault_instances/vault_instances.py +5 -5
  205. reconcile/gql_definitions/vault_policies/vault_policies.py +5 -5
  206. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +5 -5
  207. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
  208. reconcile/integrations_manager.py +3 -3
  209. reconcile/jenkins_worker_fleets.py +9 -8
  210. reconcile/jira_permissions_validator.py +2 -2
  211. reconcile/ldap_groups/integration.py +1 -1
  212. reconcile/ocm/types.py +35 -57
  213. reconcile/ocm_aws_infrastructure_access.py +1 -1
  214. reconcile/ocm_clusters.py +4 -4
  215. reconcile/ocm_labels/integration.py +3 -2
  216. reconcile/ocm_machine_pools.py +33 -27
  217. reconcile/openshift_base.py +113 -4
  218. reconcile/openshift_cluster_bots.py +1 -1
  219. reconcile/openshift_namespace_labels.py +1 -1
  220. reconcile/openshift_namespaces.py +97 -101
  221. reconcile/openshift_resources_base.py +6 -2
  222. reconcile/openshift_rhcs_certs.py +27 -29
  223. reconcile/openshift_rolebindings.py +7 -11
  224. reconcile/openshift_saas_deploy.py +4 -5
  225. reconcile/openshift_saas_deploy_change_tester.py +9 -7
  226. reconcile/openshift_serviceaccount_tokens.py +2 -2
  227. reconcile/openshift_upgrade_watcher.py +1 -1
  228. reconcile/oum/labelset.py +5 -3
  229. reconcile/oum/models.py +1 -4
  230. reconcile/prometheus_rules_tester/integration.py +3 -3
  231. reconcile/quay_mirror.py +1 -1
  232. reconcile/queries.py +6 -0
  233. reconcile/rhidp/common.py +3 -5
  234. reconcile/rhidp/sso_client/base.py +16 -5
  235. reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
  236. reconcile/skupper_network/integration.py +2 -2
  237. reconcile/slack_usergroups.py +31 -11
  238. reconcile/status_board.py +6 -6
  239. reconcile/statuspage/atlassian.py +7 -7
  240. reconcile/statuspage/page.py +4 -9
  241. reconcile/templating/lib/rendering.py +3 -3
  242. reconcile/templating/renderer.py +2 -2
  243. reconcile/terraform_cloudflare_dns.py +3 -3
  244. reconcile/terraform_cloudflare_resources.py +5 -5
  245. reconcile/terraform_cloudflare_users.py +3 -2
  246. reconcile/terraform_init/integration.py +2 -2
  247. reconcile/terraform_repo.py +16 -12
  248. reconcile/terraform_resources.py +6 -6
  249. reconcile/terraform_tgw_attachments.py +20 -18
  250. reconcile/terraform_vpc_resources/integration.py +3 -1
  251. reconcile/typed_queries/cost_report/app_names.py +1 -1
  252. reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
  253. reconcile/typed_queries/saas_files.py +11 -11
  254. reconcile/typed_queries/status_board.py +2 -2
  255. reconcile/unleash_feature_toggles/integration.py +4 -2
  256. reconcile/utils/acs/base.py +6 -3
  257. reconcile/utils/acs/policies.py +2 -2
  258. reconcile/utils/aws_api.py +51 -20
  259. reconcile/utils/aws_api_typed/organization.py +4 -2
  260. reconcile/utils/binary.py +7 -12
  261. reconcile/utils/deadmanssnitch_api.py +1 -1
  262. reconcile/utils/early_exit_cache.py +8 -10
  263. reconcile/utils/gitlab_api.py +7 -5
  264. reconcile/utils/glitchtip/client.py +6 -2
  265. reconcile/utils/glitchtip/models.py +25 -28
  266. reconcile/utils/gql.py +4 -7
  267. reconcile/utils/instrumented_wrappers.py +1 -1
  268. reconcile/utils/internal_groups/client.py +2 -2
  269. reconcile/utils/internal_groups/models.py +8 -17
  270. reconcile/utils/jinja2/utils.py +2 -5
  271. reconcile/utils/jobcontroller/controller.py +2 -2
  272. reconcile/utils/jobcontroller/models.py +17 -1
  273. reconcile/utils/json.py +43 -1
  274. reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
  275. reconcile/utils/membershipsources/models.py +16 -23
  276. reconcile/utils/membershipsources/resolver.py +4 -2
  277. reconcile/utils/merge_request_manager/merge_request_manager.py +1 -1
  278. reconcile/utils/merge_request_manager/parser.py +4 -4
  279. reconcile/utils/metrics.py +5 -5
  280. reconcile/utils/models.py +304 -82
  281. reconcile/utils/mr/notificator.py +1 -1
  282. reconcile/utils/mr/user_maintenance.py +3 -2
  283. reconcile/utils/oc.py +246 -201
  284. reconcile/utils/ocm/addons.py +0 -1
  285. reconcile/utils/ocm/base.py +17 -20
  286. reconcile/utils/ocm/cluster_groups.py +1 -1
  287. reconcile/utils/ocm/identity_providers.py +2 -2
  288. reconcile/utils/ocm/labels.py +1 -1
  289. reconcile/utils/ocm/products.py +8 -8
  290. reconcile/utils/ocm/service_log.py +1 -1
  291. reconcile/utils/ocm/sre_capability_labels.py +20 -13
  292. reconcile/utils/openshift_resource.py +5 -0
  293. reconcile/utils/pagerduty_api.py +5 -2
  294. reconcile/utils/promotion_state.py +6 -11
  295. reconcile/utils/raw_github_api.py +1 -1
  296. reconcile/utils/rhcsv2_certs.py +1 -4
  297. reconcile/utils/rosa/session.py +16 -0
  298. reconcile/utils/runtime/integration.py +1 -1
  299. reconcile/utils/saasherder/interfaces.py +13 -20
  300. reconcile/utils/saasherder/models.py +23 -20
  301. reconcile/utils/saasherder/saasherder.py +46 -24
  302. reconcile/utils/slack_api.py +2 -2
  303. reconcile/utils/structs.py +1 -1
  304. reconcile/utils/terraform_client.py +1 -1
  305. reconcile/utils/terrascript_aws_client.py +47 -43
  306. reconcile/utils/unleash/server.py +2 -8
  307. reconcile/utils/vault.py +5 -12
  308. reconcile/utils/vcs.py +8 -8
  309. reconcile/vault_replication.py +1 -1
  310. tools/cli_commands/cost_report/cost_management_api.py +3 -3
  311. tools/cli_commands/cost_report/view.py +7 -6
  312. tools/cli_commands/erv2.py +1 -1
  313. tools/qontract_cli.py +6 -5
  314. tools/template_validation.py +3 -1
  315. {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.dist-info}/WHEEL +0 -0
  316. {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.dist-info}/entry_points.txt +0 -0
@@ -7,7 +7,7 @@ from collections.abc import (
7
7
  from typing import Any
8
8
 
9
9
  import yaml
10
- from kubernetes.client import ( # type: ignore[attr-defined]
10
+ from kubernetes.client import (
11
11
  ApiClient,
12
12
  V1ConfigMap,
13
13
  V1ObjectMeta,
@@ -20,6 +20,7 @@ from reconcile.gql_definitions.automated_actions.instance import (
20
20
  AutomatedActionExternalResourceFlushElastiCacheV1,
21
21
  AutomatedActionExternalResourceRdsRebootV1,
22
22
  AutomatedActionExternalResourceRdsSnapshotV1,
23
+ AutomatedActionOpenshiftTriggerCronjobV1,
23
24
  AutomatedActionOpenshiftWorkloadDeleteV1,
24
25
  AutomatedActionOpenshiftWorkloadRestartArgumentV1,
25
26
  AutomatedActionOpenshiftWorkloadRestartV1,
@@ -82,7 +83,7 @@ class AutomatedActionsConfigIntegration(
82
83
  query_func = gql.get_api().query
83
84
  return {
84
85
  "automated_actions_instances": [
85
- c.dict() for c in self.get_automated_actions_instances(query_func)
86
+ c.model_dump() for c in self.get_automated_actions_instances(query_func)
86
87
  ]
87
88
  }
88
89
 
@@ -167,7 +168,7 @@ class AutomatedActionsConfigIntegration(
167
168
  case AutomatedActionActionListV1():
168
169
  # no special handling needed, just dump the values
169
170
  parameters.extend(
170
- arg.dict(exclude_none=True, exclude_defaults=True)
171
+ arg.model_dump(exclude_none=True, exclude_defaults=True)
171
172
  for arg in action.action_list_arguments or []
172
173
  )
173
174
  case AutomatedActionExternalResourceFlushElastiCacheV1():
@@ -205,6 +206,17 @@ class AutomatedActionsConfigIntegration(
205
206
  "account": f"^{rds_snapshot_er.provisioner.name}$",
206
207
  "identifier": rds_snapshot_arg.identifier,
207
208
  })
209
+ case AutomatedActionOpenshiftTriggerCronjobV1():
210
+ parameters.extend(
211
+ {
212
+ # all parameter values are regexes in the OPA policy
213
+ # therefore, cluster and namespace must be fixed to the current strings
214
+ "cluster": f"^{arg.namespace.cluster.name}$",
215
+ "namespace": f"^{arg.namespace.name}$",
216
+ "cronjob": arg.cronjob,
217
+ }
218
+ for arg in action.openshift_trigger_cronjob_arguments
219
+ )
208
220
  case AutomatedActionOpenshiftWorkloadDeleteV1():
209
221
  parameters.extend(
210
222
  {
@@ -257,7 +269,7 @@ class AutomatedActionsConfigIntegration(
257
269
  {
258
270
  "users": {user.username: sorted(user.roles) for user in users},
259
271
  "roles": {
260
- role: [policy.dict() for policy in policies]
272
+ role: [policy.model_dump() for policy in policies]
261
273
  for role, policies in roles.items()
262
274
  },
263
275
  },
@@ -42,14 +42,14 @@ QONTRACT_INTEGRATION_VERSION = make_semver(1, 0, 0)
42
42
 
43
43
 
44
44
  class AwsAccountMgmtIntegrationParams(PydanticRunParams):
45
- account_name: str | None
45
+ account_name: str | None = None
46
46
  flavor: str
47
47
  organization_account_role: str = "OrganizationAccountAccessRole"
48
48
  default_tags: dict[str, str] = {}
49
49
  initial_user_name: str = "terraform"
50
50
  initial_user_policy_arn: str = "arn:aws:iam::aws:policy/AdministratorAccess"
51
51
  initial_user_secret_vault_path: str = (
52
- "app-sre-v2/creds/terraform/{account_name}/config"
52
+ "app-sre-v2/creds/terraform/{account_name}/config" # noqa: RUF027
53
53
  )
54
54
  # To avoid the accidental deletion of the resource file, explicitly set the
55
55
  # qontract.cli option in the integration extraArgs!
@@ -76,9 +76,9 @@ class AwsAccountMgmtIntegration(
76
76
  query_func, account_name=self.params.account_name
77
77
  )
78
78
  return {
79
- "payer_accounts": [account.dict() for account in payer_accounts],
79
+ "payer_accounts": [account.model_dump() for account in payer_accounts],
80
80
  "non_organization_accounts": [
81
- account.dict() for account in non_organization_accounts
81
+ account.model_dump() for account in non_organization_accounts
82
82
  ],
83
83
  }
84
84
 
@@ -98,7 +98,7 @@ class AwsAccountMgmtIntegration(
98
98
  lstrip_blocks=True,
99
99
  keep_trailing_newline=True,
100
100
  ).render({
101
- "accountRequest": account_request.dict(by_alias=True),
101
+ "accountRequest": account_request.model_dump(by_alias=True),
102
102
  "uid": uid,
103
103
  "settings": settings,
104
104
  "timestamp": int(utc_now().timestamp()),
@@ -187,7 +187,7 @@ class AwsAccountMgmtIntegration(
187
187
  template=account_template,
188
188
  account_request=account_request,
189
189
  uid=uid,
190
- settings=self.params.dict(),
190
+ settings=self.params.model_dump(),
191
191
  ),
192
192
  account_request_file_path=f"data/{account_request.path.strip('/')}",
193
193
  )
@@ -35,7 +35,7 @@ class Quota(Protocol):
35
35
  quota_code: str
36
36
  value: float
37
37
 
38
- def dict(self) -> dict[str, Any]: ...
38
+ def model_dump(self) -> dict[str, Any]: ...
39
39
 
40
40
 
41
41
  class Contact(Protocol):
@@ -44,7 +44,7 @@ class Contact(Protocol):
44
44
  email: str
45
45
  phone_number: str
46
46
 
47
- def dict(self) -> dict[str, Any]: ...
47
+ def model_dump(self) -> dict[str, Any]: ...
48
48
 
49
49
 
50
50
  class AWSReconciler:
@@ -167,7 +167,7 @@ class AWSReconciler:
167
167
  self, aws_api: AWSApi, name: str, quotas: Iterable[Quota]
168
168
  ) -> list[str] | None:
169
169
  """Request service quota changes."""
170
- quotas_dict = [q.dict() for q in quotas]
170
+ quotas_dict = [q.model_dump() for q in quotas]
171
171
  with self.state.transaction(
172
172
  state_key(name, TASK_REQUEST_SERVICE_QUOTA)
173
173
  ) as _state:
@@ -40,15 +40,12 @@ QONTRACT_INTEGRATION = "aws_ami_cleanup"
40
40
  MANAGED_TAG = {"Key": "managed_by_integration", "Value": QONTRACT_INTEGRATION}
41
41
 
42
42
 
43
- class AWSAmi(BaseModel):
43
+ class AWSAmi(BaseModel, frozen=True):
44
44
  name: str
45
45
  image_id: str
46
46
  creation_date: datetime
47
47
  snapshot_ids: list[str]
48
48
 
49
- class Config:
50
- frozen = True
51
-
52
49
 
53
50
  def get_aws_amis_from_launch_templates(ec2_client: EC2Client) -> set[str]:
54
51
  amis = set()
@@ -176,7 +173,7 @@ def run(dry_run: bool, thread_pool_size: int, defer: Callable | None = None) ->
176
173
  # Build AWSApi object. We will use all those accounts listed in ami_accounts since
177
174
  # we will also need to look for used AMIs.
178
175
  accounts_dicted = [
179
- account.dict(by_alias=True)
176
+ account.model_dump(by_alias=True)
180
177
  for account in aws_accounts or []
181
178
  if account.name in ami_accounts
182
179
  ]
@@ -1,17 +1,19 @@
1
1
  import logging
2
+ import re
2
3
  from collections.abc import (
3
- Callable,
4
4
  Iterable,
5
5
  Mapping,
6
6
  )
7
7
  from typing import Any
8
8
 
9
9
  from reconcile import queries
10
+ from reconcile.typed_queries.aws_account_tags import get_aws_account_tags
11
+ from reconcile.typed_queries.external_resources import get_settings
10
12
  from reconcile.utils.aws_api import AWSApi
11
- from reconcile.utils.defer import defer
12
13
 
13
14
  QONTRACT_INTEGRATION = "aws-ami-share"
14
- MANAGED_TAG = {"Key": "managed_by_integration", "Value": QONTRACT_INTEGRATION}
15
+
16
+ MANAGED_TAG = {"managed_by_integration": QONTRACT_INTEGRATION}
15
17
 
16
18
 
17
19
  def filter_accounts(accounts: Iterable[dict[str, Any]]) -> list[dict[str, Any]]:
@@ -37,65 +39,70 @@ def get_region(
37
39
  return region
38
40
 
39
41
 
40
- @defer
41
- def run(dry_run: bool, defer: Callable | None = None) -> None:
42
+ def share_ami(
43
+ dry_run: bool,
44
+ src_account: Mapping[str, Any],
45
+ share: Mapping[str, Any],
46
+ default_tags: dict[str, str],
47
+ aws_api: AWSApi,
48
+ ) -> None:
49
+ dst_account = share["account"]
50
+ regex = re.compile(share["regex"])
51
+ region = get_region(share, src_account, dst_account)
52
+ src_amis = aws_api.get_amis_details(src_account, src_account, regex, region)
53
+ dst_amis = aws_api.get_amis_details(dst_account, src_account, regex, region)
54
+
55
+ for ami_id, src_ami_tags in src_amis.items():
56
+ dst_ami_tags = dst_amis.get(ami_id)
57
+ if dst_ami_tags is None:
58
+ logging.info([
59
+ "share_ami",
60
+ src_account["name"],
61
+ dst_account["name"],
62
+ ami_id,
63
+ ])
64
+ if not dry_run:
65
+ aws_api.share_ami(src_account, dst_account["uid"], ami_id, region)
66
+ dst_account_tags = default_tags | get_aws_account_tags(
67
+ dst_account.get("organization", None)
68
+ )
69
+ desired_tags = src_ami_tags | dst_account_tags | MANAGED_TAG
70
+ current_tags = dst_ami_tags or {}
71
+
72
+ if desired_tags != current_tags:
73
+ logging.info([
74
+ "tag_shared_ami",
75
+ dst_account["name"],
76
+ ami_id,
77
+ desired_tags,
78
+ ])
79
+ if not dry_run:
80
+ aws_api.create_tags(dst_account, ami_id, desired_tags)
81
+
82
+
83
+ def run(dry_run: bool) -> None:
42
84
  accounts = queries.get_aws_accounts(sharing=True)
43
85
  sharing_accounts = filter_accounts(accounts)
44
86
  settings = queries.get_app_interface_settings()
45
- aws_api = AWSApi(1, sharing_accounts, settings=settings, init_users=False)
46
- if defer:
47
- defer(aws_api.cleanup)
48
-
49
- for src_account in sharing_accounts:
50
- sharing = src_account.get("sharing")
51
- if not sharing:
52
- continue
53
- for share in sharing:
54
- if share["provider"] != "ami":
55
- continue
56
- dst_account = share["account"]
57
- regex = share["regex"]
58
- region = get_region(share, src_account, dst_account)
59
- src_amis = aws_api.get_amis_details(src_account, src_account, regex, region)
60
- dst_amis = aws_api.get_amis_details(dst_account, src_account, regex, region)
61
-
62
- for src_ami in src_amis:
63
- src_ami_id = src_ami["image_id"]
64
- found_dst_amis = [d for d in dst_amis if d["image_id"] == src_ami_id]
65
- if not found_dst_amis:
66
- logging.info([
67
- "share_ami",
68
- src_account["name"],
69
- dst_account["name"],
70
- src_ami_id,
71
- ])
72
- if not dry_run:
73
- aws_api.share_ami(
74
- src_account, dst_account["uid"], src_ami_id, region
75
- )
76
- # we assume an unshared ami does not have tags
77
- found_dst_amis = [{"image_id": src_ami_id, "tags": []}]
78
-
79
- dst_ami = found_dst_amis[0]
80
- dst_ami_id = dst_ami["image_id"]
81
- dst_ami_tags = dst_ami["tags"]
82
- if MANAGED_TAG not in dst_ami_tags:
83
- logging.info([
84
- "tag_shared_ami",
85
- dst_account["name"],
86
- dst_ami_id,
87
- MANAGED_TAG,
88
- ])
89
- if not dry_run:
90
- aws_api.create_tag(dst_account, dst_ami_id, MANAGED_TAG)
91
- src_ami_tags = src_ami["tags"]
92
- for src_tag in src_ami_tags:
93
- if src_tag not in dst_ami_tags:
94
- logging.info([
95
- "tag_shared_ami",
96
- dst_account["name"],
97
- dst_ami_id,
98
- src_tag,
99
- ])
100
- if not dry_run:
101
- aws_api.create_tag(dst_account, dst_ami_id, src_tag)
87
+ try:
88
+ default_tags = get_settings().default_tags
89
+ except ValueError:
90
+ # no external resources settings found
91
+ default_tags = {}
92
+
93
+ with AWSApi(
94
+ 1,
95
+ sharing_accounts,
96
+ settings=settings,
97
+ init_users=False,
98
+ ) as aws_api:
99
+ for src_account in sharing_accounts:
100
+ for share in src_account.get("sharing") or []:
101
+ if share["provider"] == "ami":
102
+ share_ami(
103
+ dry_run=dry_run,
104
+ src_account=src_account,
105
+ share=share,
106
+ default_tags=default_tags,
107
+ aws_api=aws_api,
108
+ )
@@ -82,7 +82,7 @@ class AwsSamlIdpIntegration(QontractReconcileIntegration[AwsSamlIdpIntegrationPa
82
82
  if not query_func:
83
83
  query_func = gql.get_api().query
84
84
  return {
85
- "accounts": [c.dict() for c in self.get_aws_accounts(query_func)],
85
+ "accounts": [c.model_dump() for c in self.get_aws_accounts(query_func)],
86
86
  }
87
87
 
88
88
  def get_aws_accounts(
@@ -125,7 +125,9 @@ class AwsSamlIdpIntegration(QontractReconcileIntegration[AwsSamlIdpIntegrationPa
125
125
  aws_accounts = self.get_aws_accounts(
126
126
  gql_api.query, account_name=self.params.account_name
127
127
  )
128
- aws_accounts_dict = [account.dict(by_alias=True) for account in aws_accounts]
128
+ aws_accounts_dict = [
129
+ account.model_dump(by_alias=True) for account in aws_accounts
130
+ ]
129
131
  try:
130
132
  default_tags = get_settings().default_tags
131
133
  except ValueError:
@@ -143,7 +145,7 @@ class AwsSamlIdpIntegration(QontractReconcileIntegration[AwsSamlIdpIntegrationPa
143
145
  for saml_idp_config in self.build_saml_idp_config(
144
146
  aws_accounts,
145
147
  saml_idp_name=self.params.saml_idp_name,
146
- saml_metadata=self.get_saml_metadata(self.params.saml_metadata_url),
148
+ saml_metadata=self.get_saml_metadata(str(self.params.saml_metadata_url)),
147
149
  ):
148
150
  ts.populate_saml_idp(
149
151
  account_name=saml_idp_config.account_name,
@@ -6,10 +6,11 @@ from collections.abc import (
6
6
  )
7
7
  from typing import (
8
8
  Any,
9
+ Self,
9
10
  TypedDict,
10
11
  )
11
12
 
12
- from pydantic import BaseModel, root_validator, validator
13
+ from pydantic import BaseModel, field_validator, model_validator
13
14
 
14
15
  from reconcile.gql_definitions.aws_saml_roles.aws_accounts import (
15
16
  AWSAccountV1,
@@ -59,7 +60,8 @@ class AwsSamlRolesIntegrationParams(PydanticRunParams):
59
60
  extended_early_exit_cache_ttl_seconds: int = 3600
60
61
  log_cached_log_output: bool = False
61
62
 
62
- @validator("max_session_duration_hours")
63
+ @field_validator("max_session_duration_hours")
64
+ @classmethod
63
65
  def max_session_duration_range(cls, v: str | int) -> int:
64
66
  if 1 <= int(v) <= 12:
65
67
  return int(v)
@@ -70,7 +72,8 @@ class CustomPolicy(BaseModel):
70
72
  name: str
71
73
  policy: dict[str, Any]
72
74
 
73
- @validator("name")
75
+ @field_validator("name")
76
+ @classmethod
74
77
  def name_size(cls, v: str) -> str:
75
78
  """Check the policy name size.
76
79
 
@@ -82,7 +85,8 @@ class CustomPolicy(BaseModel):
82
85
  )
83
86
  return v
84
87
 
85
- @validator("policy")
88
+ @field_validator("policy")
89
+ @classmethod
86
90
  def policy_size(cls, v: dict[str, Any]) -> dict[str, Any]:
87
91
  """Check the policy size.
88
92
 
@@ -105,7 +109,8 @@ class AwsRole(BaseModel):
105
109
  custom_policies: list[CustomPolicy]
106
110
  managed_policies: list[ManagedPolicy]
107
111
 
108
- @validator("name")
112
+ @field_validator("name")
113
+ @classmethod
109
114
  def name_size(cls, v: str) -> str:
110
115
  """Check the role name size.
111
116
 
@@ -117,29 +122,23 @@ class AwsRole(BaseModel):
117
122
  )
118
123
  return v
119
124
 
120
- @root_validator
121
- def validate_policies(cls, values: dict[str, Any]) -> dict[str, Any]:
125
+ @model_validator(mode="after")
126
+ def validate_policies(self) -> Self:
122
127
  """Check the policies.
123
128
 
124
129
  See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html
125
130
  """
126
- custom_policies = values.get("custom_policies", [])
127
- managed_policies = values.get("managed_policies", [])
128
- if len(custom_policies) + len(managed_policies) > 20:
131
+ if len(self.custom_policies) + len(self.managed_policies) > 20:
129
132
  raise ValueError(
130
- f"The role '{values['name']}' has too many policies. AWS roles can have at most 20 policies (via quota increase). Please consider consolidating the policies."
133
+ f"The role '{self.name}' has too many policies. AWS roles can have at most 20 policies (via quota increase). Please consider consolidating the policies."
131
134
  )
132
- cp_names = [cp.name for cp in custom_policies]
135
+ cp_names = [cp.name for cp in self.custom_policies]
133
136
  if len(set(cp_names)) != len(cp_names):
134
- raise ValueError(
135
- f"The role '{values['name']}' has duplicate custom policies."
136
- )
137
- mp_names = [mp.name for mp in managed_policies]
137
+ raise ValueError(f"The role '{self.name}' has duplicate custom policies.")
138
+ mp_names = [mp.name for mp in self.managed_policies]
138
139
  if len(set(mp_names)) != len(mp_names):
139
- raise ValueError(
140
- f"The role '{values['name']}' has duplicate managed policies."
141
- )
142
- return values
140
+ raise ValueError(f"The role '{self.name}' has duplicate managed policies.")
141
+ return self
143
142
 
144
143
 
145
144
  class RunnerParams(TypedDict):
@@ -164,7 +163,7 @@ class AwsSamlRolesIntegration(
164
163
  if not query_func:
165
164
  query_func = gql.get_api().query
166
165
  return {
167
- "roles": [c.dict() for c in self.get_roles(query_func)],
166
+ "roles": [c.model_dump() for c in self.get_roles(query_func)],
168
167
  }
169
168
 
170
169
  def get_aws_accounts(
@@ -252,7 +251,9 @@ class AwsSamlRolesIntegration(
252
251
  aws_accounts = self.get_aws_accounts(
253
252
  gql_api.query, account_name=self.params.account_name
254
253
  )
255
- aws_accounts_dict = [account.dict(by_alias=True) for account in aws_accounts]
254
+ aws_accounts_dict = [
255
+ account.model_dump(by_alias=True) for account in aws_accounts
256
+ ]
256
257
  aws_roles = self.get_roles(gql_api.query, account_name=self.params.account_name)
257
258
  try:
258
259
  default_tags = get_settings().default_tags
@@ -7,12 +7,7 @@ from enum import StrEnum
7
7
  from typing import Any
8
8
 
9
9
  import semver
10
- from pydantic import (
11
- BaseModel,
12
- ValidationError,
13
- root_validator,
14
- validator,
15
- )
10
+ from pydantic import BaseModel, ValidationError, field_validator, model_validator
16
11
 
17
12
  from reconcile.aws_version_sync.merge_request_manager.merge_request import (
18
13
  Renderer,
@@ -81,7 +76,7 @@ class SupportedResourceProvider(StrEnum):
81
76
  ELASTICACHE = "elasticache"
82
77
 
83
78
 
84
- class ExternalResource(BaseModel):
79
+ class ExternalResource(BaseModel, arbitrary_types_allowed=True):
85
80
  namespace_file: str | None = None
86
81
  provider: str = "aws"
87
82
  provisioner: ExternalResourceProvisioner
@@ -94,9 +89,6 @@ class ExternalResource(BaseModel):
94
89
  # used to map AWS cache name to resource_identifier
95
90
  redis_replication_group_id: str | None = None
96
91
 
97
- class Config:
98
- arbitrary_types_allowed = True
99
-
100
92
  @property
101
93
  def key(self) -> tuple:
102
94
  return (
@@ -106,7 +98,8 @@ class ExternalResource(BaseModel):
106
98
  self.resource_identifier,
107
99
  )
108
100
 
109
- @validator("resource_engine_version", pre=True)
101
+ @field_validator("resource_engine_version", mode="before")
102
+ @classmethod
110
103
  def parse_resource_engine_version(
111
104
  cls, v: str | semver.VersionInfo
112
105
  ) -> semver.VersionInfo:
@@ -114,7 +107,8 @@ class ExternalResource(BaseModel):
114
107
  return v
115
108
  return parse_semver(str(v), optional_minor_and_patch=True)
116
109
 
117
- @root_validator(pre=True)
110
+ @model_validator(mode="before")
111
+ @classmethod
118
112
  def set_resource_engine_version_format(cls, values: dict) -> dict:
119
113
  resource_engine_version, resource_engine_version_format = (
120
114
  str(values.get("resource_engine_version")),
@@ -62,8 +62,8 @@ class QontractServerDatafileDiff(BaseModel):
62
62
 
63
63
  datafilepath: str
64
64
  datafileschema: str
65
- old: dict[str, Any] | None
66
- new: dict[str, Any] | None
65
+ old: dict[str, Any] | None = None
66
+ new: dict[str, Any] | None = None
67
67
 
68
68
  @property
69
69
  def old_datafilepath(self) -> str | None:
@@ -119,7 +119,7 @@ class QontractServerResourcefileDiffState(BaseModel):
119
119
  content: str
120
120
  resourcefileschema: str | None = Field(..., alias="$schema")
121
121
  sha256sum: str
122
- backrefs: list[QontractServerResourcefileBackref] | None
122
+ backrefs: list[QontractServerResourcefileBackref] | None = None
123
123
 
124
124
 
125
125
  class QontractServerResourcefileDiff(BaseModel):
@@ -155,7 +155,8 @@ class ChangeLogIntegration(QontractReconcileIntegration[ChangeLogIntegrationPara
155
155
  changes = aggregate_resource_changes(
156
156
  bundle_changes=aggregate_file_moves(parse_bundle_changes(diff)),
157
157
  content_store={
158
- c.path: c.dict(by_alias=True) for c in namespaces + jenkins_configs
158
+ c.path: c.model_dump(by_alias=True)
159
+ for c in namespaces + jenkins_configs
159
160
  },
160
161
  supported_schemas={
161
162
  "/openshift/namespace-1.yml",
@@ -239,4 +240,4 @@ class ChangeLogIntegration(QontractReconcileIntegration[ChangeLogIntegrationPara
239
240
  change_log.items, key=lambda i: i.merged_at, reverse=True
240
241
  )
241
242
  if not dry_run:
242
- integration_state.add(BUNDLE_DIFFS_OBJ, change_log.dict(), force=True)
243
+ integration_state.add(BUNDLE_DIFFS_OBJ, change_log.model_dump(), force=True)
@@ -140,7 +140,7 @@ def write_coverage_report_to_mr(
140
140
  approver_reachability = set()
141
141
  for d in change_decisions:
142
142
  approvers = [
143
- f"{cr.context} - {' '.join([f'@{a.org_username}' if a.tag_on_merge_requests else a.org_username for a in cr.approvers])}"
143
+ f"{cr.context} - {' '.join([f'@{a.org_username}' if (a.tag_on_merge_requests or len(cr.approvers) == 1) else a.org_username for a in cr.approvers])}"
144
144
  for cr in d.change_responsibles
145
145
  ]
146
146
  if d.coverable_by_fragment_decisions:
reconcile/cli.py CHANGED
@@ -50,8 +50,8 @@ from reconcile.utils.unleash import get_feature_toggle_state
50
50
  TERRAFORM_VERSION = ["1.6.6"]
51
51
  TERRAFORM_VERSION_REGEX = r"^Terraform\sv([\d]+\.[\d]+\.[\d]+)$"
52
52
 
53
- OC_VERSIONS = ["4.16.2", "4.12.46", "4.10.15"]
54
- OC_VERSION_REGEX = r"^Client\sVersion:\s([\d]+\.[\d]+\.[\d]+)$"
53
+ OC_VERSIONS = ["4.19.0", "4.16.2"]
54
+ OC_VERSION_REGEX = r"^Client\sVersion:\s([\d]+\.[\d]+\.[\d]+)"
55
55
 
56
56
  HELM_VERSIONS = ["3.11.1"]
57
57
  HELM_VERSION_REGEX = r"^version.BuildInfo{Version:\"v([\d]+\.[\d]+\.[\d]+)\".*$"
@@ -2855,6 +2855,36 @@ def ocm_addons_upgrade_scheduler_org(
2855
2855
  default=bool(os.environ.get("IGNORE_STS_CLUSTERS")),
2856
2856
  help="Ignore STS clusters",
2857
2857
  )
2858
+ @click.option(
2859
+ "--job-controller-cluster",
2860
+ help="The cluster holding the job-controller namepsace",
2861
+ required=False,
2862
+ envvar="JOB_CONTROLLER_CLUSTER",
2863
+ )
2864
+ @click.option(
2865
+ "--job-controller-namespace",
2866
+ help="The namespace used for ROSA jobs",
2867
+ required=False,
2868
+ envvar="JOB_CONTROLLER_NAMESPACE",
2869
+ )
2870
+ @click.option(
2871
+ "--rosa-job-service-account",
2872
+ help="The service-account used for ROSA jobs",
2873
+ required=False,
2874
+ envvar="ROSA_JOB_SERVICE_ACCOUNT",
2875
+ )
2876
+ @click.option(
2877
+ "--rosa-job-image",
2878
+ help="The container image to use to run ROSA cli command jobs",
2879
+ required=False,
2880
+ envvar="ROSA_JOB_IMAGE",
2881
+ )
2882
+ @click.option(
2883
+ "--rosa-role",
2884
+ help="The role to assume in the ROSA cluster account",
2885
+ required=False,
2886
+ envvar="ROSA_ROLE",
2887
+ )
2858
2888
  @click.pass_context
2859
2889
  def advanced_upgrade_scheduler(
2860
2890
  ctx: click.Context,
@@ -2862,9 +2892,21 @@ def advanced_upgrade_scheduler(
2862
2892
  org_id: Iterable[str],
2863
2893
  exclude_org_id: Iterable[str],
2864
2894
  ignore_sts_clusters: bool,
2895
+ job_controller_cluster: str | None,
2896
+ job_controller_namespace: str | None,
2897
+ rosa_job_service_account: str | None,
2898
+ rosa_role: str | None,
2899
+ rosa_job_image: str | None,
2865
2900
  ) -> None:
2866
- from reconcile.aus.advanced_upgrade_service import AdvancedUpgradeServiceIntegration
2867
- from reconcile.aus.base import AdvancedUpgradeSchedulerBaseIntegrationParams
2901
+ from reconcile.aus.advanced_upgrade_service import (
2902
+ QONTRACT_INTEGRATION,
2903
+ QONTRACT_INTEGRATION_VERSION,
2904
+ AdvancedUpgradeServiceIntegration,
2905
+ )
2906
+ from reconcile.aus.base import (
2907
+ AdvancedUpgradeSchedulerBaseIntegrationParams,
2908
+ RosaRoleUpgradeHandlerParams,
2909
+ )
2868
2910
 
2869
2911
  run_class_integration(
2870
2912
  integration=AdvancedUpgradeServiceIntegration(
@@ -2873,6 +2915,22 @@ def advanced_upgrade_scheduler(
2873
2915
  ocm_organization_ids=set(org_id),
2874
2916
  excluded_ocm_organization_ids=set(exclude_org_id),
2875
2917
  ignore_sts_clusters=ignore_sts_clusters,
2918
+ rosa_role_upgrade_handler_params=RosaRoleUpgradeHandlerParams(
2919
+ job_controller_cluster=job_controller_cluster,
2920
+ job_controller_namespace=job_controller_namespace,
2921
+ rosa_job_service_account=rosa_job_service_account,
2922
+ rosa_role=rosa_role,
2923
+ rosa_job_image=rosa_job_image,
2924
+ integration_name=QONTRACT_INTEGRATION,
2925
+ integration_version=QONTRACT_INTEGRATION_VERSION,
2926
+ )
2927
+ if all([
2928
+ job_controller_cluster,
2929
+ job_controller_namespace,
2930
+ rosa_job_service_account,
2931
+ rosa_role,
2932
+ ])
2933
+ else None,
2876
2934
  )
2877
2935
  ),
2878
2936
  ctx=ctx,
@@ -466,7 +466,7 @@ class DashdotdbDORA(DashdotdbBase):
466
466
  ]
467
467
 
468
468
  def _github_compare_commits(self, rc: RepoChanges, repo: str) -> list[Commit]:
469
- if not rc.repo_url:
469
+ if not rc.repo_url or not rc.ref_from or not rc.ref_to:
470
470
  return []
471
471
 
472
472
  return [
@@ -119,4 +119,4 @@ def run(
119
119
 
120
120
 
121
121
  def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
122
- return {doc.name: doc.dict() for doc in get_slo_documents()}
122
+ return {doc.name: doc.model_dump() for doc in get_slo_documents()}