qontract-reconcile 0.10.2.dev361__py3-none-any.whl → 0.10.2.dev430__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 (351) hide show
  1. {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/METADATA +13 -12
  2. {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/RECORD +351 -345
  3. reconcile/acs_rbac.py +2 -2
  4. reconcile/aus/advanced_upgrade_service.py +18 -12
  5. reconcile/aus/base.py +134 -32
  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 +8 -8
  14. reconcile/aws_account_manager/reconciler.py +3 -3
  15. reconcile/aws_ami_cleanup/integration.py +8 -12
  16. reconcile/aws_ami_share.py +69 -62
  17. reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
  18. reconcile/aws_iam_keys.py +1 -0
  19. reconcile/aws_saml_idp/integration.py +12 -4
  20. reconcile/aws_saml_roles/integration.py +30 -23
  21. reconcile/aws_version_sync/integration.py +6 -12
  22. reconcile/change_owners/bundle.py +3 -3
  23. reconcile/change_owners/change_log_tracking.py +3 -2
  24. reconcile/change_owners/change_owners.py +1 -1
  25. reconcile/change_owners/diff.py +0 -2
  26. reconcile/checkpoint.py +11 -3
  27. reconcile/cli.py +93 -10
  28. reconcile/dashdotdb_dora.py +5 -12
  29. reconcile/dashdotdb_slo.py +1 -1
  30. reconcile/database_access_manager.py +123 -117
  31. reconcile/dynatrace_token_provider/integration.py +1 -1
  32. reconcile/endpoints_discovery/integration.py +4 -1
  33. reconcile/endpoints_discovery/merge_request.py +1 -1
  34. reconcile/endpoints_discovery/merge_request_manager.py +8 -8
  35. reconcile/external_resources/factories.py +4 -6
  36. reconcile/external_resources/integration.py +1 -1
  37. reconcile/external_resources/manager.py +8 -6
  38. reconcile/external_resources/meta.py +0 -1
  39. reconcile/external_resources/metrics.py +1 -1
  40. reconcile/external_resources/model.py +19 -15
  41. reconcile/external_resources/reconciler.py +7 -4
  42. reconcile/external_resources/secrets_sync.py +4 -7
  43. reconcile/external_resources/state.py +26 -16
  44. reconcile/fleet_labeler/integration.py +1 -1
  45. reconcile/gabi_authorized_users.py +5 -2
  46. reconcile/gcp_image_mirror.py +2 -2
  47. reconcile/github_org.py +1 -1
  48. reconcile/github_owners.py +4 -0
  49. reconcile/gitlab_housekeeping.py +13 -15
  50. reconcile/gitlab_members.py +6 -12
  51. reconcile/gitlab_owners.py +15 -11
  52. reconcile/gitlab_permissions.py +8 -12
  53. reconcile/glitchtip_project_alerts/integration.py +3 -1
  54. reconcile/gql_definitions/acs/acs_instances.py +5 -5
  55. reconcile/gql_definitions/acs/acs_policies.py +5 -5
  56. reconcile/gql_definitions/acs/acs_rbac.py +5 -5
  57. reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +5 -5
  58. reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +5 -5
  59. reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +5 -5
  60. reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
  61. reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
  62. reconcile/gql_definitions/automated_actions/instance.py +46 -7
  63. reconcile/gql_definitions/aws_account_manager/aws_accounts.py +5 -5
  64. reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +15 -5
  65. reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +27 -66
  66. reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +15 -5
  67. reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +15 -5
  68. reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
  69. reconcile/gql_definitions/aws_version_sync/clusters.py +5 -5
  70. reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
  71. reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
  72. reconcile/gql_definitions/change_owners/queries/self_service_roles.py +5 -5
  73. reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +5 -5
  74. reconcile/gql_definitions/common/alerting_services_settings.py +5 -5
  75. reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
  76. reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
  77. reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
  78. reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
  79. reconcile/gql_definitions/common/app_interface_roles.py +5 -5
  80. reconcile/gql_definitions/common/app_interface_state_settings.py +5 -5
  81. reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
  82. reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
  83. reconcile/gql_definitions/common/apps.py +5 -5
  84. reconcile/gql_definitions/common/aws_vpc_requests.py +15 -5
  85. reconcile/gql_definitions/common/aws_vpcs.py +5 -5
  86. reconcile/gql_definitions/common/clusters.py +5 -5
  87. reconcile/gql_definitions/common/clusters_minimal.py +5 -5
  88. reconcile/gql_definitions/common/clusters_with_dms.py +5 -5
  89. reconcile/gql_definitions/common/clusters_with_peering.py +5 -5
  90. reconcile/gql_definitions/common/github_orgs.py +5 -5
  91. reconcile/gql_definitions/common/jira_settings.py +5 -5
  92. reconcile/gql_definitions/common/jiralert_settings.py +5 -5
  93. reconcile/gql_definitions/common/ldap_settings.py +5 -5
  94. reconcile/gql_definitions/common/namespaces.py +5 -5
  95. reconcile/gql_definitions/common/namespaces_minimal.py +7 -5
  96. reconcile/gql_definitions/common/ocm_env_telemeter.py +5 -5
  97. reconcile/gql_definitions/common/ocm_environments.py +5 -5
  98. reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
  99. reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -5
  100. reconcile/gql_definitions/common/pipeline_providers.py +5 -5
  101. reconcile/gql_definitions/common/quay_instances.py +5 -5
  102. reconcile/gql_definitions/common/quay_orgs.py +5 -5
  103. reconcile/gql_definitions/common/reserved_networks.py +5 -5
  104. reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
  105. reconcile/gql_definitions/common/saas_files.py +5 -5
  106. reconcile/gql_definitions/common/saas_target_namespaces.py +5 -5
  107. reconcile/gql_definitions/common/saasherder_settings.py +5 -5
  108. reconcile/gql_definitions/common/slack_workspaces.py +5 -5
  109. reconcile/gql_definitions/common/smtp_client_settings.py +5 -5
  110. reconcile/gql_definitions/common/state_aws_account.py +5 -5
  111. reconcile/gql_definitions/common/users.py +5 -5
  112. reconcile/gql_definitions/common/users_with_paths.py +5 -5
  113. reconcile/gql_definitions/cost_report/app_names.py +5 -5
  114. reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
  115. reconcile/gql_definitions/cost_report/settings.py +5 -5
  116. reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +5 -5
  117. reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +5 -5
  118. reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
  119. reconcile/gql_definitions/email_sender/apps.py +5 -5
  120. reconcile/gql_definitions/email_sender/emails.py +5 -5
  121. reconcile/gql_definitions/email_sender/users.py +5 -5
  122. reconcile/gql_definitions/endpoints_discovery/apps.py +5 -5
  123. reconcile/gql_definitions/external_resources/aws_accounts.py +5 -5
  124. reconcile/gql_definitions/external_resources/external_resources_modules.py +5 -5
  125. reconcile/gql_definitions/external_resources/external_resources_namespaces.py +33 -6
  126. reconcile/gql_definitions/external_resources/external_resources_settings.py +5 -5
  127. reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
  128. reconcile/gql_definitions/fleet_labeler/fleet_labels.py +5 -5
  129. reconcile/gql_definitions/fragments/aus_organization.py +5 -5
  130. reconcile/gql_definitions/fragments/aws_account_common.py +7 -5
  131. reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
  132. reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
  133. reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
  134. reconcile/gql_definitions/fragments/aws_organization.py +33 -0
  135. reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
  136. reconcile/gql_definitions/fragments/aws_vpc_request.py +7 -5
  137. reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
  138. reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
  139. reconcile/gql_definitions/fragments/disable.py +5 -5
  140. reconcile/gql_definitions/fragments/email_service.py +5 -5
  141. reconcile/gql_definitions/fragments/email_user.py +5 -5
  142. reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
  143. reconcile/gql_definitions/fragments/membership_source.py +5 -5
  144. reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
  145. reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
  146. reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
  147. reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
  148. reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
  149. reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
  150. reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
  151. reconcile/gql_definitions/fragments/resource_values.py +5 -5
  152. reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
  153. reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
  154. reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
  155. reconcile/gql_definitions/fragments/terraform_state.py +5 -5
  156. reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
  157. reconcile/gql_definitions/fragments/user.py +5 -5
  158. reconcile/gql_definitions/fragments/vault_secret.py +5 -5
  159. reconcile/gql_definitions/gcp/gcp_docker_repos.py +5 -5
  160. reconcile/gql_definitions/gcp/gcp_projects.py +5 -5
  161. reconcile/gql_definitions/gitlab_members/gitlab_instances.py +5 -5
  162. reconcile/gql_definitions/gitlab_members/permissions.py +5 -5
  163. reconcile/gql_definitions/glitchtip/glitchtip_instance.py +5 -5
  164. reconcile/gql_definitions/glitchtip/glitchtip_project.py +5 -5
  165. reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +5 -5
  166. reconcile/gql_definitions/integrations/integrations.py +5 -5
  167. reconcile/gql_definitions/introspection.json +724 -129
  168. reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +5 -5
  169. reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +5 -5
  170. reconcile/gql_definitions/jira/jira_servers.py +5 -5
  171. reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +9 -5
  172. reconcile/gql_definitions/jumphosts/jumphosts.py +5 -5
  173. reconcile/gql_definitions/ldap_groups/roles.py +5 -5
  174. reconcile/gql_definitions/ldap_groups/settings.py +5 -5
  175. reconcile/gql_definitions/maintenance/maintenances.py +5 -5
  176. reconcile/gql_definitions/membershipsources/roles.py +5 -5
  177. reconcile/gql_definitions/ocm_labels/clusters.py +5 -5
  178. reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
  179. reconcile/gql_definitions/openshift_cluster_bots/clusters.py +5 -5
  180. reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
  181. reconcile/gql_definitions/openshift_groups/managed_roles.py +5 -5
  182. reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +5 -5
  183. reconcile/gql_definitions/quay_membership/quay_membership.py +5 -5
  184. reconcile/gql_definitions/rhcs/certs.py +25 -79
  185. reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
  186. reconcile/gql_definitions/rhidp/organizations.py +5 -5
  187. reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
  188. reconcile/gql_definitions/service_dependencies/service_dependencies.py +5 -5
  189. reconcile/gql_definitions/sharding/aws_accounts.py +5 -5
  190. reconcile/gql_definitions/sharding/ocm_organization.py +5 -5
  191. reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
  192. reconcile/gql_definitions/skupper_network/skupper_networks.py +5 -5
  193. reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
  194. reconcile/gql_definitions/slack_usergroups/permissions.py +5 -5
  195. reconcile/gql_definitions/slack_usergroups/users.py +5 -5
  196. reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
  197. reconcile/gql_definitions/status_board/status_board.py +5 -5
  198. reconcile/gql_definitions/statuspage/statuspages.py +5 -5
  199. reconcile/gql_definitions/templating/template_collection.py +5 -5
  200. reconcile/gql_definitions/templating/templates.py +5 -5
  201. reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +5 -5
  202. reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +5 -5
  203. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +5 -5
  204. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +5 -5
  205. reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +5 -5
  206. reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +5 -5
  207. reconcile/gql_definitions/terraform_init/aws_accounts.py +19 -5
  208. reconcile/gql_definitions/terraform_repo/terraform_repo.py +5 -5
  209. reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
  210. reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +30 -6
  211. reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +15 -5
  212. reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +5 -5
  213. reconcile/gql_definitions/vault_instances/vault_instances.py +5 -5
  214. reconcile/gql_definitions/vault_policies/vault_policies.py +5 -5
  215. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +5 -5
  216. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
  217. reconcile/integrations_manager.py +3 -3
  218. reconcile/jenkins_worker_fleets.py +10 -8
  219. reconcile/jira_permissions_validator.py +237 -122
  220. reconcile/ldap_groups/integration.py +1 -1
  221. reconcile/ocm/types.py +35 -57
  222. reconcile/ocm_aws_infrastructure_access.py +1 -1
  223. reconcile/ocm_clusters.py +4 -4
  224. reconcile/ocm_labels/integration.py +3 -2
  225. reconcile/ocm_machine_pools.py +33 -27
  226. reconcile/openshift_base.py +113 -4
  227. reconcile/openshift_cluster_bots.py +1 -1
  228. reconcile/openshift_namespace_labels.py +1 -1
  229. reconcile/openshift_namespaces.py +97 -101
  230. reconcile/openshift_resources_base.py +6 -2
  231. reconcile/openshift_rhcs_certs.py +74 -37
  232. reconcile/openshift_rolebindings.py +7 -11
  233. reconcile/openshift_saas_deploy.py +4 -5
  234. reconcile/openshift_saas_deploy_change_tester.py +9 -7
  235. reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
  236. reconcile/openshift_serviceaccount_tokens.py +2 -2
  237. reconcile/openshift_upgrade_watcher.py +4 -4
  238. reconcile/oum/labelset.py +5 -3
  239. reconcile/oum/models.py +1 -4
  240. reconcile/prometheus_rules_tester/integration.py +3 -3
  241. reconcile/quay_mirror.py +1 -1
  242. reconcile/queries.py +131 -0
  243. reconcile/rhidp/common.py +3 -5
  244. reconcile/rhidp/sso_client/base.py +16 -5
  245. reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
  246. reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
  247. reconcile/skupper_network/integration.py +2 -2
  248. reconcile/slack_usergroups.py +35 -14
  249. reconcile/sql_query.py +1 -0
  250. reconcile/status_board.py +6 -6
  251. reconcile/statuspage/atlassian.py +7 -7
  252. reconcile/statuspage/integrations/maintenances.py +4 -3
  253. reconcile/statuspage/page.py +4 -9
  254. reconcile/statuspage/status.py +5 -8
  255. reconcile/templating/lib/rendering.py +3 -3
  256. reconcile/templating/renderer.py +2 -2
  257. reconcile/terraform_aws_route53.py +7 -1
  258. reconcile/terraform_cloudflare_dns.py +3 -3
  259. reconcile/terraform_cloudflare_resources.py +5 -5
  260. reconcile/terraform_cloudflare_users.py +3 -2
  261. reconcile/terraform_init/integration.py +187 -23
  262. reconcile/terraform_repo.py +16 -12
  263. reconcile/terraform_resources.py +6 -6
  264. reconcile/terraform_tgw_attachments.py +27 -19
  265. reconcile/terraform_users.py +7 -0
  266. reconcile/terraform_vpc_peerings.py +14 -3
  267. reconcile/terraform_vpc_resources/integration.py +10 -1
  268. reconcile/typed_queries/aws_account_tags.py +41 -0
  269. reconcile/typed_queries/cost_report/app_names.py +1 -1
  270. reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
  271. reconcile/typed_queries/saas_files.py +11 -11
  272. reconcile/typed_queries/status_board.py +2 -2
  273. reconcile/unleash_feature_toggles/integration.py +4 -2
  274. reconcile/utils/acs/base.py +6 -3
  275. reconcile/utils/acs/policies.py +2 -2
  276. reconcile/utils/aws_api.py +51 -20
  277. reconcile/utils/aws_api_typed/api.py +38 -9
  278. reconcile/utils/aws_api_typed/cloudformation.py +149 -0
  279. reconcile/utils/aws_api_typed/logs.py +73 -0
  280. reconcile/utils/aws_api_typed/organization.py +4 -2
  281. reconcile/utils/binary.py +7 -12
  282. reconcile/utils/datetime_util.py +67 -0
  283. reconcile/utils/deadmanssnitch_api.py +1 -1
  284. reconcile/utils/differ.py +2 -3
  285. reconcile/utils/early_exit_cache.py +11 -12
  286. reconcile/utils/expiration.py +7 -3
  287. reconcile/utils/filtering.py +1 -1
  288. reconcile/utils/gitlab_api.py +7 -5
  289. reconcile/utils/glitchtip/client.py +6 -2
  290. reconcile/utils/glitchtip/models.py +25 -28
  291. reconcile/utils/gql.py +4 -7
  292. reconcile/utils/helpers.py +1 -1
  293. reconcile/utils/instrumented_wrappers.py +1 -1
  294. reconcile/utils/internal_groups/client.py +2 -2
  295. reconcile/utils/internal_groups/models.py +8 -17
  296. reconcile/utils/jinja2/utils.py +6 -101
  297. reconcile/utils/jira_client.py +82 -63
  298. reconcile/utils/jjb_client.py +7 -10
  299. reconcile/utils/jobcontroller/controller.py +2 -2
  300. reconcile/utils/jobcontroller/models.py +17 -1
  301. reconcile/utils/json.py +43 -1
  302. reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
  303. reconcile/utils/membershipsources/models.py +16 -23
  304. reconcile/utils/membershipsources/resolver.py +4 -2
  305. reconcile/utils/merge_request_manager/merge_request_manager.py +4 -4
  306. reconcile/utils/merge_request_manager/parser.py +6 -6
  307. reconcile/utils/metrics.py +5 -5
  308. reconcile/utils/models.py +304 -82
  309. reconcile/utils/mr/app_interface_reporter.py +2 -2
  310. reconcile/utils/mr/notificator.py +3 -3
  311. reconcile/utils/mr/update_access_report_base.py +3 -4
  312. reconcile/utils/mr/user_maintenance.py +3 -2
  313. reconcile/utils/oc.py +246 -201
  314. reconcile/utils/oc_filters.py +3 -3
  315. reconcile/utils/ocm/addons.py +0 -1
  316. reconcile/utils/ocm/base.py +17 -20
  317. reconcile/utils/ocm/cluster_groups.py +1 -1
  318. reconcile/utils/ocm/identity_providers.py +2 -2
  319. reconcile/utils/ocm/labels.py +1 -1
  320. reconcile/utils/ocm/products.py +8 -8
  321. reconcile/utils/ocm/search_filters.py +3 -6
  322. reconcile/utils/ocm/service_log.py +4 -6
  323. reconcile/utils/ocm/sre_capability_labels.py +20 -13
  324. reconcile/utils/openshift_resource.py +8 -3
  325. reconcile/utils/pagerduty_api.py +10 -7
  326. reconcile/utils/promotion_state.py +6 -11
  327. reconcile/utils/raw_github_api.py +1 -1
  328. reconcile/utils/rhcsv2_certs.py +86 -23
  329. reconcile/utils/rosa/session.py +16 -0
  330. reconcile/utils/runtime/integration.py +2 -3
  331. reconcile/utils/runtime/runner.py +2 -2
  332. reconcile/utils/saasherder/interfaces.py +13 -20
  333. reconcile/utils/saasherder/models.py +23 -20
  334. reconcile/utils/saasherder/saasherder.py +50 -27
  335. reconcile/utils/slack_api.py +2 -2
  336. reconcile/utils/sloth.py +171 -2
  337. reconcile/utils/structs.py +1 -1
  338. reconcile/utils/terraform_client.py +5 -4
  339. reconcile/utils/terrascript_aws_client.py +134 -74
  340. reconcile/utils/unleash/server.py +2 -8
  341. reconcile/utils/vault.py +5 -12
  342. reconcile/utils/vcs.py +8 -8
  343. reconcile/vault_replication.py +107 -42
  344. tools/app_interface_reporter.py +4 -4
  345. tools/cli_commands/cost_report/cost_management_api.py +3 -3
  346. tools/cli_commands/cost_report/view.py +7 -6
  347. tools/cli_commands/erv2.py +1 -1
  348. tools/qontract_cli.py +28 -17
  349. tools/template_validation.py +3 -1
  350. {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/WHEEL +0 -0
  351. {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/entry_points.txt +0 -0
@@ -2,18 +2,15 @@ from abc import (
2
2
  ABC,
3
3
  abstractmethod,
4
4
  )
5
- from datetime import (
6
- UTC,
7
- datetime,
8
- )
5
+ from datetime import datetime
9
6
 
10
- from dateutil.parser import isoparse
11
7
  from pydantic import BaseModel
12
8
 
13
9
  from reconcile.gql_definitions.statuspage.statuspages import (
14
10
  ManualStatusProviderV1,
15
11
  StatusProviderV1,
16
12
  )
13
+ from reconcile.utils.datetime_util import from_utc_iso_format, utc_now
17
14
 
18
15
  # This module defines the interface for status providers for components on status
19
16
  # pages. A status provider is responsible for determining the status of a component.
@@ -70,7 +67,7 @@ class ManualStatusProvider(StatusProvider, BaseModel):
70
67
  raise ValueError(
71
68
  "manual component status time window is invalid: end before start"
72
69
  )
73
- now = datetime.now(UTC)
70
+ now = utc_now()
74
71
  if self.start and now < self.start:
75
72
  return False
76
73
  return not (self.end and self.end < now)
@@ -84,8 +81,8 @@ def build_status_provider_config(
84
81
  provider specific implementation that provides the status resolution logic.
85
82
  """
86
83
  if isinstance(cfg, ManualStatusProviderV1):
87
- start = isoparse(cfg.manual.q_from) if cfg.manual.q_from else None
88
- end = isoparse(cfg.manual.until) if cfg.manual.until else None
84
+ start = from_utc_iso_format(cfg.manual.q_from) if cfg.manual.q_from else None
85
+ end = from_utc_iso_format(cfg.manual.until) if cfg.manual.until else None
89
86
  return ManualStatusProvider(
90
87
  component_status=cfg.manual.component_status,
91
88
  start=start,
@@ -18,7 +18,7 @@ from reconcile.utils.secret_reader import SecretReaderBase
18
18
 
19
19
  class TemplateData(BaseModel):
20
20
  variables: dict[str, Any]
21
- current: dict[str, Any] | None
21
+ current: dict[str, Any] | None = None
22
22
  current_with_explicit_start: bool | None = False
23
23
 
24
24
 
@@ -26,7 +26,7 @@ class TemplatePatch(Protocol):
26
26
  path: str
27
27
  identifier: str | None
28
28
 
29
- def dict(self) -> dict[str, str]: ...
29
+ def model_dump(self) -> dict[str, str]: ...
30
30
 
31
31
 
32
32
  class Template(Protocol):
@@ -36,7 +36,7 @@ class Template(Protocol):
36
36
  template: str
37
37
  overwrite: bool | None
38
38
 
39
- def dict(self) -> dict[str, str]: ...
39
+ def model_dump(self) -> dict[str, str]: ...
40
40
 
41
41
  @property
42
42
  def patch(self) -> TemplatePatch | None:
@@ -239,8 +239,8 @@ def unpack_dynamic_variables(
239
239
 
240
240
  class TemplateRendererIntegrationParams(PydanticRunParams):
241
241
  clone_repo: bool = False
242
- app_interface_root_path: str | None
243
- template_collection_name: str | None
242
+ app_interface_root_path: str | None = None
243
+ template_collection_name: str | None = None
244
244
 
245
245
 
246
246
  def join_path(base: str, sub: str) -> str:
@@ -9,6 +9,7 @@ from typing import Any
9
9
 
10
10
  from reconcile import queries
11
11
  from reconcile.status import ExitCodes
12
+ from reconcile.typed_queries.external_resources import get_settings
12
13
  from reconcile.utils import dnsutils
13
14
  from reconcile.utils.aws_api import AWSApi
14
15
  from reconcile.utils.constants import DEFAULT_THREAD_POOL_SIZE
@@ -227,13 +228,18 @@ def run(
227
228
  f"No participating AWS accounts found, consider disabling this integration, account name: {account_name}"
228
229
  )
229
230
  return
230
-
231
+ try:
232
+ default_tags = get_settings().default_tags
233
+ except ValueError:
234
+ # no external resources settings found
235
+ default_tags = None
231
236
  ts = Terrascript(
232
237
  QONTRACT_INTEGRATION,
233
238
  "",
234
239
  thread_pool_size,
235
240
  participating_accounts,
236
241
  settings=settings,
242
+ default_tags=default_tags,
237
243
  )
238
244
 
239
245
  desired_state = build_desired_state(zones, all_accounts, settings)
@@ -155,7 +155,7 @@ class TerraformCloudflareDNSIntegration(
155
155
 
156
156
  accts_per_zone = []
157
157
  for zone in query_zones.zones or []:
158
- acct = zone.account.dict(by_alias=True)
158
+ acct = zone.account.model_dump(by_alias=True)
159
159
  acct["name"] = f"{zone.account.name}-{zone.identifier}"
160
160
  accts_per_zone.append(acct)
161
161
 
@@ -369,11 +369,11 @@ def cloudflare_dns_zone_to_external_resource(
369
369
  provision_provider=DEFAULT_PROVISIONER_PROVIDER,
370
370
  provisioner={"name": f"{zone.account.name}-{zone.identifier}"},
371
371
  namespace=DEFAULT_NAMESPACE,
372
- resource=zone.dict(by_alias=True, exclude=DEFAULT_EXCLUDE_KEY),
372
+ resource=zone.model_dump(by_alias=True, exclude=DEFAULT_EXCLUDE_KEY),
373
373
  )
374
374
  external_resource_spec.resource["provider"] = DEFAULT_PROVIDER
375
375
  external_resource_spec.resource["records"] = [
376
- record.dict(by_alias=True) for record in zone.records or []
376
+ record.model_dump(by_alias=True) for record in zone.records or []
377
377
  ]
378
378
  external_resource_specs.append(external_resource_spec)
379
379
  return external_resource_specs
@@ -168,7 +168,7 @@ def _build_oc_resources(
168
168
  internal=internal,
169
169
  )
170
170
 
171
- namespace_mapping = [ns.dict() for ns in cloudflare_namespaces]
171
+ namespace_mapping = [ns.model_dump() for ns in cloudflare_namespaces]
172
172
 
173
173
  state_specs = init_specs_to_fetch(
174
174
  ri, oc_map, namespaces=namespace_mapping, override_managed_types=["Secret"]
@@ -338,7 +338,7 @@ def run(
338
338
  )
339
339
 
340
340
  if not cloudflare_namespaces:
341
- logging.info("No cloudflare namespaces were detected, nothing to do.")
341
+ logging.debug("No cloudflare namespaces were detected, nothing to do.")
342
342
  sys.exit(ExitCodes.SUCCESS)
343
343
 
344
344
  # Build Cloudflare clients
@@ -351,7 +351,7 @@ def run(
351
351
  spec
352
352
  for namespace in query_resources.namespaces
353
353
  for spec in get_external_resource_specs(
354
- namespace.dict(by_alias=True), PROVIDER_CLOUDFLARE
354
+ namespace.model_dump(by_alias=True), PROVIDER_CLOUDFLARE
355
355
  )
356
356
  if not selected_account or spec.provisioner_name == selected_account
357
357
  ]
@@ -383,7 +383,7 @@ def run(
383
383
  QONTRACT_INTEGRATION_VERSION,
384
384
  QONTRACT_TF_PREFIX,
385
385
  [
386
- acct.dict(by_alias=True) # convert CloudflareAccountV1 to dict
386
+ acct.model_dump(by_alias=True) # convert CloudflareAccountV1 to dict
387
387
  for acct in query_accounts.accounts or []
388
388
  if acct.name in cf_clients.dump() # use only if it is a registered client
389
389
  ],
@@ -442,4 +442,4 @@ def _get_cloudflare_desired_state() -> tuple[
442
442
  def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
443
443
  desired_state = _get_cloudflare_desired_state()
444
444
 
445
- return {state.__repr_name__(): state.dict() for state in desired_state}
445
+ return {str(state): state.model_dump() for state in desired_state}
@@ -88,7 +88,7 @@ class TerraformCloudflareUsers(
88
88
  if not settings.settings:
89
89
  raise RuntimeError("App interface setting not defined")
90
90
 
91
- early_exit_desired_state = cloudflare_roles.dict()
91
+ early_exit_desired_state = cloudflare_roles.model_dump()
92
92
  early_exit_desired_state.update({
93
93
  CLOUDFLARE_EMAIL_DOMAIN_ALLOW_LIST_KEY: settings.settings
94
94
  })
@@ -149,7 +149,8 @@ class TerraformCloudflareUsers(
149
149
  }
150
150
 
151
151
  accounts = [
152
- acct.dict(by_alias=True) for _, acct in account_names_to_account.items()
152
+ acct.model_dump(by_alias=True)
153
+ for _, acct in account_names_to_account.items()
153
154
  ]
154
155
 
155
156
  self._run_terraform(
@@ -1,6 +1,5 @@
1
1
  import logging
2
2
  from collections.abc import Callable
3
- from datetime import UTC, datetime
4
3
  from typing import Any
5
4
 
6
5
  import jinja2
@@ -12,12 +11,16 @@ from reconcile.gql_definitions.terraform_init.aws_accounts import (
12
11
  from reconcile.terraform_init.merge_request import Renderer, create_parser
13
12
  from reconcile.terraform_init.merge_request_manager import MergeRequestManager, MrData
14
13
  from reconcile.typed_queries.app_interface_repo_url import get_app_interface_repo_url
14
+ from reconcile.typed_queries.aws_account_tags import get_aws_account_tags
15
+ from reconcile.typed_queries.external_resources import get_settings
15
16
  from reconcile.typed_queries.github_orgs import get_github_orgs
16
17
  from reconcile.typed_queries.gitlab_instances import get_gitlab_instances
17
18
  from reconcile.utils import gql
18
19
  from reconcile.utils.aws_api_typed.api import AWSApi, AWSStaticCredentials
20
+ from reconcile.utils.datetime_util import utc_now
19
21
  from reconcile.utils.defer import defer
20
22
  from reconcile.utils.disabled_integrations import integration_is_enabled
23
+ from reconcile.utils.gql import GqlApi
21
24
  from reconcile.utils.runtime.integration import (
22
25
  PydanticRunParams,
23
26
  QontractReconcileIntegration,
@@ -31,10 +34,16 @@ QONTRACT_INTEGRATION_VERSION = make_semver(1, 0, 0)
31
34
 
32
35
 
33
36
  class TerraformInitIntegrationParams(PydanticRunParams):
34
- account_name: str | None
37
+ account_name: str | None = None
35
38
  # To avoid the accidental deletion of the resource file, explicitly set the
36
39
  # qontract.cli option in the integration extraArgs!
37
40
  state_tmpl_resource: str = "/terraform-init/terraform-state.yml"
41
+ cloudformation_template_resource: str = (
42
+ "/terraform-init/terraform-state-s3-bucket.yaml"
43
+ )
44
+ cloudformation_import_template_resource: str = (
45
+ "/terraform-init/terraform-state-s3-bucket-import.yaml"
46
+ )
38
47
  template_collection_root_path: str = "data/templating/collections/terraform-init"
39
48
 
40
49
 
@@ -55,25 +64,35 @@ class TerraformInitIntegration(
55
64
  query_func = gql.get_api().query
56
65
  return {
57
66
  "accounts": [
58
- account.dict() for account in self.get_aws_accounts(query_func)
67
+ account.model_dump() for account in self.get_aws_accounts(query_func)
59
68
  ],
60
69
  }
61
70
 
62
71
  def get_aws_accounts(
63
72
  self, query_func: Callable, account_name: str | None = None
64
73
  ) -> list[AWSAccountV1]:
65
- """Return all AWS accounts with terraform username but no terraform state set."""
74
+ """Return all AWS accounts with terraform username."""
66
75
  return [
67
76
  account
68
77
  for account in aws_accounts_query(query_func).accounts or []
69
78
  if integration_is_enabled(self.name, account)
70
79
  and (not account_name or account.name == account_name)
71
80
  and account.terraform_username
72
- and not account.terraform_state
73
81
  ]
74
82
 
83
+ @staticmethod
84
+ def get_default_tags(gql_api: GqlApi) -> dict[str, str]:
85
+ try:
86
+ return get_settings(gql_api.query).default_tags
87
+ except ValueError:
88
+ # no settings found
89
+ return {}
90
+
91
+ @staticmethod
75
92
  def render_state_collection(
76
- self, template: str, bucket_name: str, account: AWSAccountV1
93
+ template: str,
94
+ bucket_name: str,
95
+ account: AWSAccountV1,
77
96
  ) -> str:
78
97
  return jinja2.Template(
79
98
  template,
@@ -85,24 +104,114 @@ class TerraformInitIntegration(
85
104
  "account_name": account.name,
86
105
  "bucket_name": bucket_name,
87
106
  "region": account.resources_default_region,
88
- "timestamp": int(datetime.now(tz=UTC).timestamp()),
107
+ "timestamp": int(utc_now().timestamp()),
89
108
  })
90
109
 
91
110
  def reconcile_account(
92
111
  self,
93
- account_aws_api: AWSApi,
112
+ aws_api: AWSApi,
113
+ merge_request_manager: MergeRequestManager,
114
+ dry_run: bool,
115
+ account: AWSAccountV1,
116
+ state_template: str,
117
+ cloudformation_template: str,
118
+ cloudformation_import_template: str,
119
+ default_tags: dict[str, str],
120
+ ) -> None:
121
+ """
122
+ Reconcile the terraform state for a given account.
123
+
124
+ Create S3 bucket via CloudFormation and Merge Request to update template file on init.
125
+ Import existing bucket if it exists but not managed by CloudFormation.
126
+ Update CloudFormation stack if tags or template body differ.
127
+
128
+ CloudFormation stack name and bucket name is `terraform-<account_name>`.
129
+ `cloudformation_import_template` should be minimal template with identifier fields only.
130
+ `cloudformation_template` should be the full template.
131
+ Use import template to import then update stack to match full template.
132
+ This will ensure imported resources match CloudFormation template.
133
+ And all desired changes in full template are applied.
134
+ Both templates must have BucketName in Parameters.
135
+
136
+ Args:
137
+ aws_api: AWSApi: AWS API client for the target account.
138
+ merge_request_manager: MergeRequestManager: Manager to handle merge requests.
139
+ dry_run: bool: If True, do not make any changes.
140
+ account: AWSAccountV1: The AWS account to reconcile.
141
+ state_template: str: Jinja2 template for the Terraform state configuration.
142
+ cloudformation_template: str: CloudFormation template to create the S3 bucket.
143
+ cloudformation_import_template: str: CloudFormation template to import existing S3 bucket.
144
+ default_tags: dict[str, str]: Default tags to apply to the CloudFormation stack.
145
+
146
+ Returns:
147
+ None
148
+ """
149
+ bucket_name = (
150
+ account.terraform_state.bucket
151
+ if account.terraform_state
152
+ else f"terraform-{account.name}"
153
+ )
154
+
155
+ tags = default_tags | get_aws_account_tags(account.organization)
156
+
157
+ if account.terraform_state is None:
158
+ return self._provision_terraform_state(
159
+ aws_api=aws_api,
160
+ merge_request_manager=merge_request_manager,
161
+ dry_run=dry_run,
162
+ account=account,
163
+ bucket_name=bucket_name,
164
+ cloudformation_template=cloudformation_template,
165
+ state_template=state_template,
166
+ tags=tags,
167
+ )
168
+
169
+ stack = aws_api.cloudformation.get_stack(stack_name=bucket_name)
170
+
171
+ if stack is None:
172
+ return self._import_cloudformation_stack(
173
+ aws_api=aws_api,
174
+ dry_run=dry_run,
175
+ bucket_name=bucket_name,
176
+ cloudformation_import_template=cloudformation_import_template,
177
+ cloudformation_template=cloudformation_template,
178
+ tags=tags,
179
+ )
180
+
181
+ return self._reconcile_cloudformation_stack(
182
+ aws_api=aws_api,
183
+ dry_run=dry_run,
184
+ bucket_name=bucket_name,
185
+ cloudformation_template=cloudformation_template,
186
+ tags=tags,
187
+ current_tags={tag["Key"]: tag["Value"] for tag in stack.get("Tags", [])},
188
+ )
189
+
190
+ def _provision_terraform_state(
191
+ self,
192
+ aws_api: AWSApi,
94
193
  merge_request_manager: MergeRequestManager,
95
194
  dry_run: bool,
96
- state_collection: str,
97
- bucket_name: str,
98
195
  account: AWSAccountV1,
196
+ bucket_name: str,
197
+ cloudformation_template: str,
198
+ state_template: str,
199
+ tags: dict[str, str],
99
200
  ) -> None:
100
201
  logging.info("Creating bucket '%s' for account '%s'", bucket_name, account.name)
101
202
  if not dry_run:
102
- # the creation of the bucket is idempotent
103
- account_aws_api.s3.create_bucket(
104
- name=bucket_name, region=account.resources_default_region
203
+ aws_api.cloudformation.create_stack(
204
+ stack_name=bucket_name,
205
+ change_set_name=f"create-{bucket_name}",
206
+ template_body=cloudformation_template,
207
+ parameters={"BucketName": bucket_name},
208
+ tags=tags,
105
209
  )
210
+ state_collection = self.render_state_collection(
211
+ template=state_template,
212
+ bucket_name=bucket_name,
213
+ account=account,
214
+ )
106
215
  merge_request_manager.create_merge_request(
107
216
  data=MrData(
108
217
  account=account.name,
@@ -111,6 +220,55 @@ class TerraformInitIntegration(
111
220
  )
112
221
  )
113
222
 
223
+ @staticmethod
224
+ def _import_cloudformation_stack(
225
+ aws_api: AWSApi,
226
+ dry_run: bool,
227
+ bucket_name: str,
228
+ cloudformation_import_template: str,
229
+ cloudformation_template: str,
230
+ tags: dict[str, str],
231
+ ) -> None:
232
+ logging.info("Importing existing bucket %s", bucket_name)
233
+ if not dry_run:
234
+ aws_api.cloudformation.create_stack(
235
+ stack_name=bucket_name,
236
+ change_set_name=f"import-{bucket_name}",
237
+ template_body=cloudformation_import_template,
238
+ parameters={"BucketName": bucket_name},
239
+ tags=tags,
240
+ )
241
+ logging.info("Syncing stack %s after import", bucket_name)
242
+ aws_api.cloudformation.update_stack(
243
+ stack_name=bucket_name,
244
+ template_body=cloudformation_template,
245
+ parameters={"BucketName": bucket_name},
246
+ tags=tags,
247
+ )
248
+
249
+ @staticmethod
250
+ def _reconcile_cloudformation_stack(
251
+ aws_api: AWSApi,
252
+ dry_run: bool,
253
+ bucket_name: str,
254
+ cloudformation_template: str,
255
+ tags: dict[str, str],
256
+ current_tags: dict[str, str],
257
+ ) -> None:
258
+ if (
259
+ current_tags != tags
260
+ or aws_api.cloudformation.get_template_body(stack_name=bucket_name)
261
+ != cloudformation_template
262
+ ):
263
+ logging.info("Updating stack %s", bucket_name)
264
+ if not dry_run:
265
+ aws_api.cloudformation.update_stack(
266
+ stack_name=bucket_name,
267
+ template_body=cloudformation_template,
268
+ parameters={"BucketName": bucket_name},
269
+ tags=tags,
270
+ )
271
+
114
272
  @defer
115
273
  def run(self, dry_run: bool, defer: Callable | None = None) -> None:
116
274
  """Run the integration."""
@@ -144,6 +302,14 @@ class TerraformInitIntegration(
144
302
  state_template = gql_api.get_resource(path=self.params.state_tmpl_resource)[
145
303
  "content"
146
304
  ]
305
+ cloudformation_template = gql_api.get_resource(
306
+ path=self.params.cloudformation_template_resource
307
+ )["content"]
308
+ cloudformation_import_template = gql_api.get_resource(
309
+ path=self.params.cloudformation_import_template_resource
310
+ )["content"]
311
+ default_tags = self.get_default_tags(gql_api)
312
+
147
313
  for account in accounts:
148
314
  secret = self.secret_reader.read_all_secret(account.automation_token)
149
315
  with AWSApi(
@@ -153,15 +319,13 @@ class TerraformInitIntegration(
153
319
  region=account.resources_default_region,
154
320
  )
155
321
  ) as account_aws_api:
156
- bucket_name = f"terraform-{account.name}"
157
- state_collection = self.render_state_collection(
158
- state_template, bucket_name, account
159
- )
160
322
  self.reconcile_account(
161
- account_aws_api,
162
- merge_request_manager,
163
- dry_run,
164
- state_collection,
165
- bucket_name,
166
- account,
323
+ aws_api=account_aws_api,
324
+ merge_request_manager=merge_request_manager,
325
+ dry_run=dry_run,
326
+ account=account,
327
+ state_template=state_template,
328
+ cloudformation_template=cloudformation_template,
329
+ cloudformation_import_template=cloudformation_import_template,
330
+ default_tags=default_tags,
167
331
  )
@@ -41,10 +41,10 @@ class RepoOutput(BaseModel):
41
41
  project_path: str
42
42
  delete: bool
43
43
  aws_creds: VaultSecret
44
- variables: TerraformRepoVariablesV1 | None
45
- bucket: str | None
46
- region: str | None
47
- bucket_path: str | None
44
+ variables: TerraformRepoVariablesV1 | None = None
45
+ bucket: str | None = None
46
+ region: str | None = None
47
+ bucket_path: str | None = None
48
48
  require_fips: bool
49
49
  tf_version: str
50
50
 
@@ -62,8 +62,8 @@ class OutputFile(BaseModel):
62
62
  class TerraformRepoIntegrationParams(PydanticRunParams):
63
63
  output_file: str | None
64
64
  validate_git: bool
65
- gitlab_project_id: str | None
66
- gitlab_merge_request_id: int | None
65
+ gitlab_project_id: str | None = None
66
+ gitlab_merge_request_id: int | None = None
67
67
 
68
68
 
69
69
  class TerraformRepoIntegration(
@@ -168,7 +168,7 @@ class TerraformRepoIntegration(
168
168
  self.params.output_file, "w", encoding="locale"
169
169
  ) as output_file:
170
170
  yaml.safe_dump(
171
- data=output.dict(),
171
+ data=output.model_dump(),
172
172
  stream=output_file,
173
173
  explicit_start=True,
174
174
  )
@@ -177,7 +177,7 @@ class TerraformRepoIntegration(
177
177
  f"Unable to write to '{self.params.output_file}'"
178
178
  ) from None
179
179
  else:
180
- print(yaml.safe_dump(data=output.dict(), explicit_start=True))
180
+ print(yaml.safe_dump(data=output.model_dump(), explicit_start=True))
181
181
 
182
182
  return output
183
183
 
@@ -206,7 +206,7 @@ class TerraformRepoIntegration(
206
206
  keys = state.ls()
207
207
  for key in keys:
208
208
  if value := state.get(key.lstrip("/"), None):
209
- repo = TerraformRepoV1.parse_obj(value)
209
+ repo = TerraformRepoV1.model_validate(value)
210
210
  repo_list.append(repo)
211
211
 
212
212
  return repo_list
@@ -283,7 +283,7 @@ class TerraformRepoIntegration(
283
283
  for add_key, add_val in diff_result.add.items():
284
284
  # state.add already performs a json.dumps(key) so we export the
285
285
  # pydantic model as a dict to avoid a double json dump with extra quotes
286
- state.add(add_key, add_val.dict(by_alias=True), force=True)
286
+ state.add(add_key, add_val.model_dump(by_alias=True), force=True)
287
287
  for delete_key in diff_result.delete:
288
288
  state.rm(delete_key)
289
289
  for change_key, change_val in diff_result.change.items():
@@ -291,7 +291,9 @@ class TerraformRepoIntegration(
291
291
  state.rm(change_key)
292
292
  else:
293
293
  state.add(
294
- change_key, change_val.desired.dict(by_alias=True), force=True
294
+ change_key,
295
+ change_val.desired.model_dump(by_alias=True),
296
+ force=True,
295
297
  )
296
298
  except KeyError:
297
299
  pass
@@ -394,5 +396,7 @@ class TerraformRepoIntegration(
394
396
  def early_exit_desired_state(self, *args: Any, **kwargs: Any) -> dict[str, Any]:
395
397
  gqlapi = gql.get_api()
396
398
  return {
397
- "repos": [repo.dict() for repo in self.get_repos(query_func=gqlapi.query)]
399
+ "repos": [
400
+ repo.model_dump() for repo in self.get_repos(query_func=gqlapi.query)
401
+ ]
398
402
  }
@@ -137,7 +137,7 @@ def fetch_current_state(
137
137
  use_jump_host=use_jump_host,
138
138
  thread_pool_size=thread_pool_size,
139
139
  )
140
- namespaces_dicts = [ns.dict(by_alias=True) for ns in namespaces]
140
+ namespaces_dicts = [ns.model_dump(by_alias=True) for ns in namespaces]
141
141
  state_specs = ob.init_specs_to_fetch(
142
142
  ri, oc_map, namespaces=namespaces_dicts, override_managed_types=["Secret"]
143
143
  )
@@ -273,7 +273,7 @@ def setup(
273
273
  )
274
274
  else:
275
275
  ocm_map = None
276
- tf_namespaces_dicts = [ns.dict(by_alias=True) for ns in tf_namespaces]
276
+ tf_namespaces_dicts = [ns.model_dump(by_alias=True) for ns in tf_namespaces]
277
277
 
278
278
  provider_exclusions = settings.get("terraformResourcesProviderExclusions") or []
279
279
  ts.init_populate_specs(
@@ -295,16 +295,16 @@ def filter_tf_namespaces(
295
295
  ) -> list[NamespaceV1]:
296
296
  tf_namespaces = []
297
297
  for namespace_info in namespaces:
298
- if ob.is_namespace_deleted(namespace_info.dict(by_alias=True)):
298
+ if ob.is_namespace_deleted(namespace_info.model_dump(by_alias=True)):
299
299
  continue
300
- if not managed_external_resources(namespace_info.dict(by_alias=True)):
300
+ if not managed_external_resources(namespace_info.model_dump(by_alias=True)):
301
301
  continue
302
302
 
303
303
  if not account_names:
304
304
  tf_namespaces.append(namespace_info)
305
305
  continue
306
306
 
307
- specs = get_external_resource_specs(namespace_info.dict(by_alias=True))
307
+ specs = get_external_resource_specs(namespace_info.model_dump(by_alias=True))
308
308
  if not specs:
309
309
  tf_namespaces.append(namespace_info)
310
310
  continue
@@ -567,7 +567,7 @@ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
567
567
  }
568
568
  for ns_info in get_tf_namespaces():
569
569
  for spec in get_external_resource_specs(
570
- ns_info.dict(by_alias=True), provision_provider=PROVIDER_AWS
570
+ ns_info.model_dump(by_alias=True), provision_provider=PROVIDER_AWS
571
571
  ):
572
572
  resource_paths = [
573
573
  spec.resource.get("defaults"),