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
@@ -141,16 +141,16 @@ class OCMClusterAWSOperatorRole(BaseModel):
141
141
 
142
142
 
143
143
  class OCMAWSSTS(OCMClusterFlag):
144
- role_arn: str | None
145
- support_role_arn: str | None
146
- oidc_endpoint_url: str | None
147
- operator_iam_roles: list[OCMClusterAWSOperatorRole] | None
148
- instance_iam_roles: dict[str, str] | None
149
- operator_role_prefix: str | None
144
+ role_arn: str | None = None
145
+ support_role_arn: str | None = None
146
+ oidc_endpoint_url: str | None = None
147
+ operator_iam_roles: list[OCMClusterAWSOperatorRole] | None = None
148
+ instance_iam_roles: dict[str, str] | None = None
149
+ operator_role_prefix: str | None = None
150
150
 
151
151
 
152
152
  class OCMClusterAWSSettings(BaseModel):
153
- sts: OCMAWSSTS | None
153
+ sts: OCMAWSSTS | None = None
154
154
 
155
155
  @property
156
156
  def sts_enabled(self) -> bool:
@@ -264,21 +264,21 @@ class OCMCluster(BaseModel):
264
264
  product: OCMModelLink
265
265
  identity_providers: OCMCollectionLink
266
266
 
267
- aws: OCMClusterAWSSettings | None
267
+ aws: OCMClusterAWSSettings | None = None
268
268
 
269
269
  version: OCMClusterVersion
270
270
 
271
271
  hypershift: OCMClusterFlag
272
272
 
273
- console: OCMClusterConsole | None
273
+ console: OCMClusterConsole | None = None
274
274
 
275
- api: OCMClusterAPI | None
275
+ api: OCMClusterAPI | None = None
276
276
 
277
- dns: OCMClusterDns | None
277
+ dns: OCMClusterDns | None = None
278
278
 
279
- external_configuration: OCMExternalConfiguration | None
279
+ external_configuration: OCMExternalConfiguration | None = None
280
280
 
281
- external_auth_config: OCMExternalAuthConfig | None
281
+ external_auth_config: OCMExternalAuthConfig | None = None
282
282
 
283
283
  def minor_version(self) -> str:
284
284
  version_info = parse_semver(self.version.raw_id)
@@ -570,15 +570,12 @@ class OCMOIdentityProviderGithub(OCMOIdentityProvider):
570
570
  )
571
571
 
572
572
 
573
- class OCMOIdentityProviderOidcOpenIdClaims(BaseModel):
573
+ class OCMOIdentityProviderOidcOpenIdClaims(BaseModel, frozen=True):
574
574
  email: list[str]
575
575
  name: list[str] = []
576
576
  preferred_username: list[str]
577
577
  groups: list[str] = []
578
578
 
579
- class Config:
580
- frozen = True
581
-
582
579
 
583
580
  class OCMOIdentityProviderOidcOpenId(BaseModel):
584
581
  client_id: str
@@ -618,11 +615,11 @@ class OCMAddonUpgradePolicy(BaseModel):
618
615
  id: str
619
616
  addon_id: str
620
617
  cluster_id: str
621
- next_run: str | None
622
- schedule: str | None
618
+ next_run: str | None = None
619
+ schedule: str | None = None
623
620
  schedule_type: str
624
621
  version: str
625
- state: str | None
622
+ state: str | None = None
626
623
 
627
624
 
628
625
  def build_label_container(
@@ -17,7 +17,7 @@ def add_user_to_cluster_group(
17
17
  """
18
18
  ocm_api.post(
19
19
  build_cluster_group_users_url(cluster_id, group),
20
- OCMClusterUser(id=user_name).dict(by_alias=True),
20
+ OCMClusterUser(id=user_name).model_dump(by_alias=True),
21
21
  )
22
22
 
23
23
 
@@ -42,7 +42,7 @@ def add_identity_provider(
42
42
  )
43
43
  ocm_api.post(
44
44
  api_path=ocm_cluster.identity_providers.href,
45
- data=idp.dict(by_alias=True, exclude_none=True),
45
+ data=idp.model_dump(by_alias=True, exclude_none=True),
46
46
  )
47
47
 
48
48
 
@@ -55,7 +55,7 @@ def update_identity_provider(
55
55
  raise ValueError(f"IDP {idp.name} does not have a href!")
56
56
  ocm_api.patch(
57
57
  api_path=idp.href,
58
- data=idp.dict(by_alias=True, exclude_none=True, exclude={"name"}),
58
+ data=idp.model_dump(by_alias=True, exclude_none=True, exclude={"name"}),
59
59
  )
60
60
 
61
61
 
@@ -159,7 +159,7 @@ def build_container_for_prefix(
159
159
 
160
160
  return LabelContainer(
161
161
  labels={
162
- strip_prefix_if_needed(label.key): label.copy(
162
+ strip_prefix_if_needed(label.key): label.model_copy(
163
163
  update={"key": strip_prefix_if_needed(label.key)}
164
164
  )
165
165
  for label in container.labels.values()
@@ -178,11 +178,11 @@ class OCMProductOsd(OCMProduct):
178
178
  ],
179
179
  provision_shard_id=provision_shard_id,
180
180
  hypershift=cluster["hypershift"]["enabled"],
181
- fips=cluster.get("fips"),
181
+ fips=cluster.get("fips") or False,
182
182
  )
183
183
 
184
184
  if not cluster["ccs"]["enabled"]:
185
- cluster_spec_data = spec.dict()
185
+ cluster_spec_data = spec.model_dump()
186
186
  cluster_spec_data["storage"] = (
187
187
  cluster["storage_quota"]["value"] // BYTES_IN_GIGABYTE
188
188
  )
@@ -229,7 +229,7 @@ class OCMProductOsd(OCMProduct):
229
229
  "compute_machine_type": {"id": default_machine_pool.instance_type},
230
230
  }
231
231
  if default_machine_pool.autoscale is not None:
232
- spec["autoscale_compute"] = default_machine_pool.autoscale.dict()
232
+ spec["autoscale_compute"] = default_machine_pool.autoscale.model_dump()
233
233
  else:
234
234
  spec["compute"] = default_machine_pool.replicas
235
235
  return spec
@@ -259,7 +259,7 @@ class OCMProductOsd(OCMProduct):
259
259
  if (duwm := cluster.spec.disable_user_workload_monitoring) is not None
260
260
  else True
261
261
  ),
262
- "fips": bool(cluster.spec.fips),
262
+ "fips": cluster.spec.fips,
263
263
  }
264
264
 
265
265
  # Workaround to enable type checks.
@@ -429,7 +429,7 @@ class OCMProductRosa(OCMProduct):
429
429
  subnet_ids=cluster["aws"].get("subnet_ids"),
430
430
  availability_zones=cluster["nodes"].get("availability_zones"),
431
431
  oidc_endpoint_url=oidc_endpoint_url,
432
- fips=cluster.get("fips"),
432
+ fips=cluster.get("fips") or False,
433
433
  )
434
434
 
435
435
  machine_pools = [
@@ -474,7 +474,7 @@ class OCMProductRosa(OCMProduct):
474
474
  "compute_machine_type": {"id": default_machine_pool.instance_type},
475
475
  }
476
476
  if default_machine_pool.autoscale is not None:
477
- spec["autoscale_compute"] = default_machine_pool.autoscale.dict()
477
+ spec["autoscale_compute"] = default_machine_pool.autoscale.model_dump()
478
478
  else:
479
479
  spec["compute"] = default_machine_pool.replicas
480
480
  return spec
@@ -517,7 +517,7 @@ class OCMProductRosa(OCMProduct):
517
517
  if (duwm := cluster.spec.disable_user_workload_monitoring) is not None
518
518
  else True
519
519
  ),
520
- "fips": bool(cluster.spec.fips),
520
+ "fips": cluster.spec.fips,
521
521
  }
522
522
 
523
523
  provision_shard_id = cluster.spec.provision_shard_id
@@ -706,7 +706,7 @@ class OCMProductHypershift(OCMProduct):
706
706
  availability_zones=cluster["nodes"].get("availability_zones"),
707
707
  hypershift=cluster["hypershift"]["enabled"],
708
708
  oidc_endpoint_url=oidc_endpoint_url,
709
- fips=cluster.get("fips"),
709
+ fips=cluster.get("fips") or False,
710
710
  )
711
711
 
712
712
  network = OCMClusterNetwork(
@@ -55,6 +55,6 @@ def create_service_log(
55
55
  return OCMClusterServiceLog(
56
56
  **ocm_api.post(
57
57
  api_path=CLUSTER_SERVICE_LOGS_CREATE_ENDPOINT,
58
- data=service_log.dict(by_alias=True),
58
+ data=service_log.model_dump(by_alias=True),
59
59
  )
60
60
  )
@@ -1,7 +1,7 @@
1
1
  from typing import Any
2
2
 
3
- from pydantic import Field
4
- from pydantic.fields import ModelField
3
+ from pydantic import WithJsonSchema
4
+ from pydantic.fields import FieldInfo
5
5
 
6
6
  from reconcile.utils.ocm.base import (
7
7
  LabelContainer,
@@ -22,11 +22,11 @@ def sre_capability_label_key(
22
22
  return f"sre-capabilities.{sre_capability}.{config_atom}"
23
23
 
24
24
 
25
- def labelset_groupfield(group_prefix: str) -> Any:
25
+ def labelset_groupfield(group_prefix: str) -> WithJsonSchema:
26
26
  """
27
27
  Helper function to build the FieldMeta for a labelset field that groups labels.
28
28
  """
29
- return Field(group_by_prefix=group_prefix)
29
+ return WithJsonSchema({"group_by_prefix": group_prefix})
30
30
 
31
31
 
32
32
  def build_labelset(
@@ -36,16 +36,23 @@ def build_labelset(
36
36
  Instantiates a dataclass from a set of labels.
37
37
  """
38
38
  raw_data = {
39
- field.alias: _labelset_field_value(labels, field)
40
- for field in dataclass.__fields__.values()
39
+ field.alias or name: _labelset_field_value(labels, name, field)
40
+ for name, field in dataclass.model_fields.items()
41
41
  }
42
42
  return dataclass(**raw_data)
43
43
 
44
44
 
45
- def _labelset_field_value(labels: LabelContainer, field: ModelField) -> Any | None:
46
- key_prefix = field.field_info.extra.get("group_by_prefix")
47
- if key_prefix:
48
- return build_container_for_prefix(
49
- labels, key_prefix, strip_key_prefix=True
50
- ).get_values_dict()
51
- return labels.get_label_value(field.alias)
45
+ def _labelset_field_value(
46
+ labels: LabelContainer, name: str, field: FieldInfo
47
+ ) -> Any | None:
48
+ schema = next((m for m in field.metadata if isinstance(m, WithJsonSchema)), None)
49
+ if (
50
+ schema is None
51
+ or not schema.json_schema
52
+ or "group_by_prefix" not in schema.json_schema
53
+ ):
54
+ return labels.get_label_value(field.alias or name)
55
+
56
+ return build_container_for_prefix(
57
+ labels, schema.json_schema["group_by_prefix"], strip_key_prefix=True
58
+ ).get_values_dict()
@@ -5,6 +5,7 @@ import base64
5
5
  import contextlib
6
6
  import copy
7
7
  import hashlib
8
+ import logging
8
9
  import re
9
10
  from threading import Lock
10
11
  from typing import TYPE_CHECKING, Any
@@ -601,6 +602,10 @@ class ResourceInventory:
601
602
  resource: OpenshiftResource,
602
603
  privileged: bool = False,
603
604
  ) -> None:
605
+ if cluster not in self._clusters:
606
+ logging.error(f"Cluster {cluster} not initialized in ResourceInventory")
607
+ return
608
+
604
609
  if resource.kind_and_group in self._clusters[cluster][namespace]:
605
610
  kind = resource.kind_and_group
606
611
  else:
@@ -52,10 +52,13 @@ class PagerDutyTarget(Protocol):
52
52
  which must be implemented by a class to be compatible."""
53
53
 
54
54
  name: str
55
- instance: PagerDutyInstance
56
55
  escalation_policy_id: str | None
57
56
  schedule_id: str | None
58
57
 
58
+ @property
59
+ def instance(self) -> PagerDutyInstance:
60
+ pass
61
+
59
62
 
60
63
  class PagerDutyConfig(BaseModel):
61
64
  """PagerDuty Config."""
@@ -189,7 +192,7 @@ def get_pagerduty_name(user: PagerDutyUser) -> str:
189
192
  return user.pagerduty_username or user.org_username
190
193
 
191
194
 
192
- @retry(no_retry_exceptions=PagerDutyTargetError)
195
+ @retry(no_retry_exceptions=(PagerDutyTargetError,))
193
196
  def get_usernames_from_pagerduty(
194
197
  pagerduties: Iterable[PagerDutyTarget],
195
198
  users: Iterable[PagerDutyUser],
@@ -3,13 +3,12 @@ from collections import defaultdict
3
3
 
4
4
  from pydantic import (
5
5
  BaseModel,
6
- Extra,
7
6
  )
8
7
 
9
8
  from reconcile.utils.state import State
10
9
 
11
10
 
12
- class PromotionData(BaseModel):
11
+ class PromotionData(BaseModel, extra="forbid"):
13
12
  """
14
13
  A class that strictly corresponds to the json stored in S3.
15
14
 
@@ -20,17 +19,13 @@ class PromotionData(BaseModel):
20
19
 
21
20
  # The success is primarily used for SAPM auto-promotions
22
21
  success: bool
23
- target_config_hash: str | None
24
- saas_file: str | None
25
- check_in: str | None
22
+ target_config_hash: str | None = None
23
+ saas_file: str | None = None
24
+ check_in: str | None = None
26
25
  # Whether this promotion has ever succeeded
27
26
  # Note, this shouldnt be overridden on subsequent promotions of same ref
28
27
  # This attribute is primarily used by saasherder validations
29
- has_succeeded_once: bool | None
30
-
31
- class Config:
32
- smart_union = True
33
- extra = Extra.forbid
28
+ has_succeeded_once: bool | None = None
34
29
 
35
30
 
36
31
  class PromotionState:
@@ -107,5 +102,5 @@ class PromotionState:
107
102
  self, sha: str, channel: str, target_uid: str, data: PromotionData
108
103
  ) -> None:
109
104
  state_key_v2 = f"promotions_v2/{channel}/{target_uid}/{sha}"
110
- self._state.add(state_key_v2, data.dict(), force=True)
105
+ self._state.add(state_key_v2, data.model_dump(), force=True)
111
106
  logging.info("Uploaded %s to %s", data, state_key_v2)
@@ -76,7 +76,7 @@ class RawGithubApi:
76
76
  if login is not None
77
77
  ]
78
78
 
79
- def team_invitations(self, org_id: str, team_id: str) -> list[str]:
79
+ def team_invitations(self, org_id: str | int, team_id: str | int) -> list[str]:
80
80
  invitations = self.query(f"/organizations/{org_id}/team/{team_id}/invitations")
81
81
 
82
82
  return [
@@ -9,15 +9,12 @@ from cryptography.x509.oid import NameOID
9
9
  from pydantic import BaseModel, Field
10
10
 
11
11
 
12
- class RhcsV2Cert(BaseModel):
12
+ class RhcsV2Cert(BaseModel, validate_by_name=True, validate_by_alias=True):
13
13
  certificate: str = Field(alias="tls.crt")
14
14
  private_key: str = Field(alias="tls.key")
15
15
  ca_cert: str = Field(alias="ca.crt")
16
16
  expiration_timestamp: int
17
17
 
18
- class Config:
19
- allow_population_by_field_name = True
20
-
21
18
 
22
19
  def extract_cert(text: str) -> re.Match:
23
20
  # The CA webform returns an HTML page with inline JS that builds an array of “outputList”
@@ -178,6 +178,22 @@ class RosaSession:
178
178
  )
179
179
  result.write_logs_to_logger(logging.info)
180
180
 
181
+ def upgrade_rosa_roles(
182
+ self,
183
+ cluster_name: str,
184
+ upgrade_version: str,
185
+ policy_version: str,
186
+ dry_run: bool,
187
+ ) -> None:
188
+ logging.info(
189
+ f"Upgrade roles in AWS account {self.aws_account_id} to {upgrade_version}"
190
+ )
191
+ if not dry_run:
192
+ result = self.cli_execute(
193
+ f"rosa upgrade roles -c {cluster_name} --cluster-version {upgrade_version} --policy-version {policy_version} -y -m=auto"
194
+ )
195
+ result.write_logs_to_logger(logging.info)
196
+
181
197
 
182
198
  def generate_rosa_creation_script(
183
199
  cluster_name: str, cluster: OCMSpec, dry_run: bool
@@ -119,7 +119,7 @@ class PydanticRunParams(RunParams, BaseModel):
119
119
  def copy_and_update(
120
120
  self: PydanticRunParamsSelfTypeVar, update: dict[str, Any]
121
121
  ) -> PydanticRunParamsSelfTypeVar:
122
- return self.copy(update=update)
122
+ return self.model_copy(update=update)
123
123
 
124
124
  def get(self, field: str) -> Any:
125
125
  return getattr(self, field)
@@ -1,7 +1,7 @@
1
1
  # ruff: noqa: N801
2
2
  from __future__ import annotations
3
3
 
4
- from collections.abc import Mapping, Sequence, Set
4
+ from collections.abc import Sequence
5
5
  from typing import (
6
6
  TYPE_CHECKING,
7
7
  Any,
@@ -12,6 +12,8 @@ from typing import (
12
12
  from reconcile.utils import oc_connection_parameters
13
13
 
14
14
  if TYPE_CHECKING:
15
+ from pydantic.main import IncEx
16
+
15
17
  from reconcile.gql_definitions.fragments.saas_slo_document import SLODocument
16
18
  from reconcile.utils.secret_reader import HasSecret
17
19
 
@@ -27,18 +29,12 @@ class SaasFileSecretParameters(Protocol):
27
29
  @property
28
30
  def secret(self) -> HasSecret: ...
29
31
 
30
- def dict(
31
- self,
32
- *,
33
- by_alias: bool = False,
34
- include: AbstractSetIntStr | MappingIntStrAny | None = None,
32
+ def model_dump(
33
+ self, *, by_alias: bool = False, include: IncEx | None = None
35
34
  ) -> dict[str, Any]: ...
36
35
 
37
36
 
38
37
  SaasSecretParameters = Sequence[SaasFileSecretParameters] | None
39
- # Taken from pydantic.typing
40
- AbstractSetIntStr = Set[int | str]
41
- MappingIntStrAny = Mapping[int | str, Any]
42
38
 
43
39
 
44
40
  @runtime_checkable
@@ -212,11 +208,8 @@ class SaasResourceTemplateTargetNamespace(Protocol):
212
208
  @property
213
209
  def cluster(self) -> oc_connection_parameters.Cluster: ...
214
210
 
215
- def dict(
216
- self,
217
- *,
218
- by_alias: bool = False,
219
- include: AbstractSetIntStr | MappingIntStrAny | None = None,
211
+ def model_dump(
212
+ self, *, by_alias: bool = False, include: IncEx | None = None
220
213
  ) -> dict[str, Any]: ...
221
214
 
222
215
 
@@ -249,7 +242,7 @@ class SaasResourceTemplateTargetPromotion(Protocol):
249
242
  @property
250
243
  def promotion_data(self) -> Sequence[SaasPromotionData] | None: ...
251
244
 
252
- def dict(self, *, by_alias: bool = False) -> dict[str, Any]: ...
245
+ def model_dump(self, *, by_alias: bool = False) -> dict[str, Any]: ...
253
246
 
254
247
 
255
248
  class Channel(Protocol):
@@ -274,7 +267,7 @@ class SaasPromotion(Protocol):
274
267
  @property
275
268
  def subscribe(self) -> list[Channel] | None: ...
276
269
 
277
- def dict(self, *, by_alias: bool = False) -> dict[str, Any]: ...
270
+ def model_dump(self, *, by_alias: bool = False) -> dict[str, Any]: ...
278
271
 
279
272
 
280
273
  class SaasResourceTemplateTarget_SaasSecretParameters(Protocol):
@@ -295,7 +288,7 @@ class SaasResourceTemplateTargetUpstream(Protocol):
295
288
  @property
296
289
  def instance(self) -> SaasJenkinsInstance: ...
297
290
 
298
- def dict(self, *, by_alias: bool = False) -> dict[str, Any]: ...
291
+ def model_dump(self, *, by_alias: bool = False) -> dict[str, Any]: ...
299
292
 
300
293
 
301
294
  class SaasQuayInstance(Protocol):
@@ -315,7 +308,7 @@ class SaasResourceTemplateTargetImage(Protocol):
315
308
  @property
316
309
  def org(self) -> SaasQuayOrg: ...
317
310
 
318
- def dict(self, *, by_alias: bool = False) -> dict[str, Any]: ...
311
+ def model_dump(self, *, by_alias: bool = False) -> dict[str, Any]: ...
319
312
 
320
313
 
321
314
  class SaasResourceTemplateTarget(HasParameters, HasSecretParameters, Protocol):
@@ -344,7 +337,7 @@ class SaasResourceTemplateTarget(HasParameters, HasSecretParameters, Protocol):
344
337
  self, parent_saas_file_name: str, parent_resource_template_name: str
345
338
  ) -> str: ...
346
339
 
347
- def dict(self, *, by_alias: bool = False) -> dict[str, Any]: ...
340
+ def model_dump(self, *, by_alias: bool = False) -> dict[str, Any]: ...
348
341
 
349
342
 
350
343
  class SaasResourceTemplate(HasParameters, HasSecretParameters, Protocol):
@@ -381,7 +374,7 @@ class ManagedResourceName(Protocol):
381
374
  resource: str
382
375
  resource_names: list[str]
383
376
 
384
- def dict(self) -> dict[str, str]: ...
377
+ def model_dump(self) -> dict[str, str]: ...
385
378
 
386
379
 
387
380
  class SaasFile(HasParameters, HasSecretParameters, Protocol):
@@ -7,10 +7,7 @@ from enum import Enum
7
7
  from typing import Any, NotRequired, TypedDict
8
8
 
9
9
  from github import Github
10
- from pydantic import (
11
- BaseModel,
12
- Field,
13
- )
10
+ from pydantic import BaseModel, Field, model_validator
14
11
 
15
12
  from reconcile.gql_definitions.fragments.saas_slo_document import (
16
13
  SLODocument,
@@ -207,7 +204,12 @@ TriggerSpecUnion = (
207
204
  )
208
205
 
209
206
 
210
- class Namespace(BaseModel):
207
+ class Namespace(
208
+ BaseModel,
209
+ validate_by_name=True,
210
+ validate_by_alias=True,
211
+ arbitrary_types_allowed=True,
212
+ ):
211
213
  name: str
212
214
  environment: SaasEnvironment
213
215
  app: SaasApp
@@ -217,29 +219,19 @@ class Namespace(BaseModel):
217
219
  ..., alias="managedResourceNames"
218
220
  )
219
221
 
220
- class Config:
221
- arbitrary_types_allowed = True
222
- allow_population_by_field_name = True
223
-
224
222
 
225
- class PromotionChannelData(BaseModel):
223
+ class PromotionChannelData(BaseModel, validate_by_name=True, validate_by_alias=True):
226
224
  q_type: str = Field(..., alias="type")
227
225
 
228
- class Config:
229
- allow_population_by_field_name = True
230
226
 
231
-
232
- class ParentSaasPromotion(BaseModel):
227
+ class ParentSaasPromotion(BaseModel, validate_by_name=True, validate_by_alias=True):
233
228
  q_type: str = Field(..., alias="type")
234
- parent_saas: str | None
235
- target_config_hash: str | None
236
-
237
- class Config:
238
- allow_population_by_field_name = True
229
+ parent_saas: str | None = None
230
+ target_config_hash: str | None = None
239
231
 
240
232
 
241
233
  class PromotionData(BaseModel):
242
- channel: str | None
234
+ channel: str | None = None
243
235
  data: list[ParentSaasPromotion | PromotionChannelData] | None = None
244
236
 
245
237
 
@@ -264,6 +256,17 @@ class Promotion(BaseModel):
264
256
  saas_file_paths: list[str] | None = None
265
257
  target_paths: list[str] | None = None
266
258
 
259
+ @model_validator(mode="before")
260
+ @classmethod
261
+ def handle_gql_classes(cls, data: Any) -> Any:
262
+ if data.get("promotion_data"):
263
+ data["promotion_data"] = [
264
+ # convert a GQL class to a dict
265
+ item.model_dump() if hasattr(item, "model_dump") else item
266
+ for item in data["promotion_data"]
267
+ ]
268
+ return data
269
+
267
270
 
268
271
  @dataclass
269
272
  class ImageAuth: