qontract-reconcile 0.10.2.dev310__py3-none-any.whl → 0.10.2.dev439__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.

Potentially problematic release.


This version of qontract-reconcile might be problematic. Click here for more details.

Files changed (400) hide show
  1. {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/METADATA +13 -12
  2. {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/RECORD +396 -391
  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_ecr_image_pull_secrets.py +5 -5
  19. reconcile/aws_iam_keys.py +1 -0
  20. reconcile/aws_saml_idp/integration.py +12 -4
  21. reconcile/aws_saml_roles/integration.py +32 -25
  22. reconcile/aws_version_sync/integration.py +125 -84
  23. reconcile/change_owners/bundle.py +3 -3
  24. reconcile/change_owners/change_log_tracking.py +3 -2
  25. reconcile/change_owners/change_owners.py +1 -1
  26. reconcile/change_owners/diff.py +2 -4
  27. reconcile/checkpoint.py +12 -4
  28. reconcile/cli.py +111 -18
  29. reconcile/cluster_deployment_mapper.py +2 -3
  30. reconcile/dashdotdb_dora.py +5 -12
  31. reconcile/dashdotdb_slo.py +1 -1
  32. reconcile/database_access_manager.py +125 -121
  33. reconcile/deadmanssnitch.py +1 -5
  34. reconcile/dynatrace_token_provider/integration.py +1 -1
  35. reconcile/endpoints_discovery/integration.py +4 -1
  36. reconcile/endpoints_discovery/merge_request.py +1 -1
  37. reconcile/endpoints_discovery/merge_request_manager.py +9 -11
  38. reconcile/external_resources/factories.py +5 -12
  39. reconcile/external_resources/integration.py +1 -1
  40. reconcile/external_resources/manager.py +8 -5
  41. reconcile/external_resources/meta.py +0 -1
  42. reconcile/external_resources/metrics.py +1 -1
  43. reconcile/external_resources/model.py +20 -20
  44. reconcile/external_resources/reconciler.py +7 -4
  45. reconcile/external_resources/secrets_sync.py +10 -14
  46. reconcile/external_resources/state.py +26 -16
  47. reconcile/fleet_labeler/integration.py +1 -1
  48. reconcile/gabi_authorized_users.py +8 -5
  49. reconcile/gcp_image_mirror.py +2 -2
  50. reconcile/github_org.py +1 -1
  51. reconcile/github_owners.py +4 -0
  52. reconcile/gitlab_housekeeping.py +13 -15
  53. reconcile/gitlab_members.py +6 -12
  54. reconcile/gitlab_mr_sqs_consumer.py +2 -2
  55. reconcile/gitlab_owners.py +15 -11
  56. reconcile/gitlab_permissions.py +8 -12
  57. reconcile/glitchtip_project_alerts/integration.py +3 -1
  58. reconcile/gql_definitions/acs/acs_instances.py +10 -10
  59. reconcile/gql_definitions/acs/acs_policies.py +5 -5
  60. reconcile/gql_definitions/acs/acs_rbac.py +6 -6
  61. reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +32 -32
  62. reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +26 -26
  63. reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +6 -7
  64. reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
  65. reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
  66. reconcile/gql_definitions/automated_actions/instance.py +51 -12
  67. reconcile/gql_definitions/aws_account_manager/aws_accounts.py +11 -11
  68. reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +20 -10
  69. reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +28 -68
  70. reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +20 -10
  71. reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +20 -10
  72. reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
  73. reconcile/gql_definitions/aws_version_sync/clusters.py +10 -10
  74. reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
  75. reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
  76. reconcile/gql_definitions/change_owners/queries/self_service_roles.py +9 -9
  77. reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +18 -18
  78. reconcile/gql_definitions/common/alerting_services_settings.py +9 -9
  79. reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
  80. reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
  81. reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
  82. reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
  83. reconcile/gql_definitions/common/app_interface_roles.py +120 -0
  84. reconcile/gql_definitions/common/app_interface_state_settings.py +10 -10
  85. reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
  86. reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
  87. reconcile/gql_definitions/common/apps.py +5 -5
  88. reconcile/gql_definitions/common/aws_vpc_requests.py +22 -9
  89. reconcile/gql_definitions/common/aws_vpcs.py +11 -11
  90. reconcile/gql_definitions/common/clusters.py +37 -35
  91. reconcile/gql_definitions/common/clusters_minimal.py +14 -14
  92. reconcile/gql_definitions/common/clusters_with_dms.py +6 -6
  93. reconcile/gql_definitions/common/clusters_with_peering.py +29 -30
  94. reconcile/gql_definitions/common/github_orgs.py +10 -10
  95. reconcile/gql_definitions/common/jira_settings.py +10 -10
  96. reconcile/gql_definitions/common/jiralert_settings.py +5 -5
  97. reconcile/gql_definitions/common/ldap_settings.py +5 -5
  98. reconcile/gql_definitions/common/namespaces.py +42 -44
  99. reconcile/gql_definitions/common/namespaces_minimal.py +15 -13
  100. reconcile/gql_definitions/common/ocm_env_telemeter.py +12 -12
  101. reconcile/gql_definitions/common/ocm_environments.py +19 -19
  102. reconcile/gql_definitions/common/pagerduty_instances.py +9 -9
  103. reconcile/gql_definitions/common/pgp_reencryption_settings.py +6 -6
  104. reconcile/gql_definitions/common/pipeline_providers.py +29 -29
  105. reconcile/gql_definitions/common/quay_instances.py +5 -5
  106. reconcile/gql_definitions/common/quay_orgs.py +5 -5
  107. reconcile/gql_definitions/common/reserved_networks.py +5 -5
  108. reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
  109. reconcile/gql_definitions/common/saas_files.py +44 -44
  110. reconcile/gql_definitions/common/saas_target_namespaces.py +10 -10
  111. reconcile/gql_definitions/common/saasherder_settings.py +5 -5
  112. reconcile/gql_definitions/common/slack_workspaces.py +5 -5
  113. reconcile/gql_definitions/common/smtp_client_settings.py +19 -19
  114. reconcile/gql_definitions/common/state_aws_account.py +7 -8
  115. reconcile/gql_definitions/common/users.py +5 -5
  116. reconcile/gql_definitions/common/users_with_paths.py +5 -5
  117. reconcile/gql_definitions/cost_report/app_names.py +5 -5
  118. reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
  119. reconcile/gql_definitions/cost_report/settings.py +9 -9
  120. reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +43 -43
  121. reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +10 -10
  122. reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
  123. reconcile/gql_definitions/email_sender/apps.py +5 -5
  124. reconcile/gql_definitions/email_sender/emails.py +8 -8
  125. reconcile/gql_definitions/email_sender/users.py +6 -6
  126. reconcile/gql_definitions/endpoints_discovery/apps.py +10 -10
  127. reconcile/gql_definitions/external_resources/aws_accounts.py +9 -9
  128. reconcile/gql_definitions/external_resources/external_resources_modules.py +23 -23
  129. reconcile/gql_definitions/external_resources/external_resources_namespaces.py +494 -410
  130. reconcile/gql_definitions/external_resources/external_resources_settings.py +28 -26
  131. reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
  132. reconcile/gql_definitions/fleet_labeler/fleet_labels.py +40 -40
  133. reconcile/gql_definitions/fragments/aus_organization.py +5 -5
  134. reconcile/gql_definitions/fragments/aws_account_common.py +7 -5
  135. reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
  136. reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
  137. reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
  138. reconcile/gql_definitions/fragments/{aws_vpc_request_subnet.py → aws_organization.py} +12 -8
  139. reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
  140. reconcile/gql_definitions/fragments/aws_vpc_request.py +12 -5
  141. reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
  142. reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
  143. reconcile/gql_definitions/fragments/disable.py +5 -5
  144. reconcile/gql_definitions/fragments/email_service.py +5 -5
  145. reconcile/gql_definitions/fragments/email_user.py +5 -5
  146. reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
  147. reconcile/gql_definitions/fragments/membership_source.py +5 -5
  148. reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
  149. reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
  150. reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
  151. reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
  152. reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
  153. reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
  154. reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
  155. reconcile/gql_definitions/fragments/resource_values.py +5 -5
  156. reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
  157. reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
  158. reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
  159. reconcile/gql_definitions/fragments/terraform_state.py +5 -5
  160. reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
  161. reconcile/gql_definitions/fragments/user.py +5 -5
  162. reconcile/gql_definitions/fragments/vault_secret.py +5 -5
  163. reconcile/gql_definitions/gcp/gcp_docker_repos.py +9 -9
  164. reconcile/gql_definitions/gcp/gcp_projects.py +9 -9
  165. reconcile/gql_definitions/gitlab_members/gitlab_instances.py +9 -9
  166. reconcile/gql_definitions/gitlab_members/permissions.py +9 -9
  167. reconcile/gql_definitions/glitchtip/glitchtip_instance.py +9 -9
  168. reconcile/gql_definitions/glitchtip/glitchtip_project.py +11 -11
  169. reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +9 -9
  170. reconcile/gql_definitions/integrations/integrations.py +48 -51
  171. reconcile/gql_definitions/introspection.json +3510 -1865
  172. reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +11 -11
  173. reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +10 -10
  174. reconcile/gql_definitions/jira/jira_servers.py +5 -5
  175. reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +14 -10
  176. reconcile/gql_definitions/jumphosts/jumphosts.py +13 -13
  177. reconcile/gql_definitions/ldap_groups/roles.py +5 -5
  178. reconcile/gql_definitions/ldap_groups/settings.py +9 -9
  179. reconcile/gql_definitions/maintenance/maintenances.py +5 -5
  180. reconcile/gql_definitions/membershipsources/roles.py +5 -5
  181. reconcile/gql_definitions/ocm_labels/clusters.py +18 -19
  182. reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
  183. reconcile/gql_definitions/openshift_cluster_bots/clusters.py +22 -22
  184. reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
  185. reconcile/gql_definitions/openshift_groups/managed_roles.py +6 -6
  186. reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +10 -10
  187. reconcile/gql_definitions/quay_membership/quay_membership.py +6 -6
  188. reconcile/gql_definitions/rhcs/certs.py +33 -87
  189. reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
  190. reconcile/gql_definitions/rhidp/organizations.py +18 -18
  191. reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
  192. reconcile/gql_definitions/service_dependencies/service_dependencies.py +8 -8
  193. reconcile/gql_definitions/sharding/aws_accounts.py +10 -10
  194. reconcile/gql_definitions/sharding/ocm_organization.py +8 -8
  195. reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
  196. reconcile/gql_definitions/skupper_network/skupper_networks.py +10 -10
  197. reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
  198. reconcile/gql_definitions/slack_usergroups/permissions.py +9 -9
  199. reconcile/gql_definitions/slack_usergroups/users.py +5 -5
  200. reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
  201. reconcile/gql_definitions/status_board/status_board.py +6 -7
  202. reconcile/gql_definitions/statuspage/statuspages.py +9 -9
  203. reconcile/gql_definitions/templating/template_collection.py +5 -5
  204. reconcile/gql_definitions/templating/templates.py +5 -5
  205. reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +6 -6
  206. reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +11 -11
  207. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +11 -11
  208. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +20 -25
  209. reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +6 -6
  210. reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +12 -12
  211. reconcile/gql_definitions/terraform_init/aws_accounts.py +23 -9
  212. reconcile/gql_definitions/terraform_repo/terraform_repo.py +9 -9
  213. reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
  214. reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +450 -402
  215. reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +23 -17
  216. reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +9 -9
  217. reconcile/gql_definitions/vault_instances/vault_instances.py +61 -61
  218. reconcile/gql_definitions/vault_policies/vault_policies.py +11 -11
  219. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +8 -8
  220. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
  221. reconcile/integrations_manager.py +3 -3
  222. reconcile/jenkins_job_builder.py +1 -1
  223. reconcile/jenkins_worker_fleets.py +80 -11
  224. reconcile/jira_permissions_validator.py +237 -122
  225. reconcile/ldap_groups/integration.py +1 -1
  226. reconcile/ocm/types.py +35 -56
  227. reconcile/ocm_aws_infrastructure_access.py +1 -1
  228. reconcile/ocm_clusters.py +4 -4
  229. reconcile/ocm_labels/integration.py +3 -2
  230. reconcile/ocm_machine_pools.py +33 -27
  231. reconcile/openshift_base.py +122 -10
  232. reconcile/openshift_cluster_bots.py +5 -5
  233. reconcile/openshift_groups.py +5 -0
  234. reconcile/openshift_limitranges.py +1 -1
  235. reconcile/openshift_namespace_labels.py +1 -1
  236. reconcile/openshift_namespaces.py +97 -101
  237. reconcile/openshift_resources_base.py +10 -5
  238. reconcile/openshift_rhcs_certs.py +77 -40
  239. reconcile/openshift_rolebindings.py +230 -130
  240. reconcile/openshift_saas_deploy.py +6 -7
  241. reconcile/openshift_saas_deploy_change_tester.py +9 -7
  242. reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
  243. reconcile/openshift_serviceaccount_tokens.py +8 -7
  244. reconcile/openshift_tekton_resources.py +1 -1
  245. reconcile/openshift_upgrade_watcher.py +4 -4
  246. reconcile/openshift_users.py +5 -3
  247. reconcile/oum/labelset.py +5 -3
  248. reconcile/oum/models.py +1 -4
  249. reconcile/oum/providers.py +1 -1
  250. reconcile/prometheus_rules_tester/integration.py +4 -4
  251. reconcile/quay_mirror.py +1 -1
  252. reconcile/queries.py +131 -0
  253. reconcile/requests_sender.py +8 -3
  254. reconcile/resource_scraper.py +1 -5
  255. reconcile/rhidp/common.py +3 -5
  256. reconcile/rhidp/sso_client/base.py +19 -10
  257. reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
  258. reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
  259. reconcile/sendgrid_teammates.py +20 -9
  260. reconcile/skupper_network/integration.py +2 -2
  261. reconcile/slack_usergroups.py +35 -14
  262. reconcile/sql_query.py +1 -0
  263. reconcile/status.py +2 -2
  264. reconcile/status_board.py +6 -6
  265. reconcile/statuspage/atlassian.py +7 -7
  266. reconcile/statuspage/integrations/maintenances.py +4 -3
  267. reconcile/statuspage/page.py +4 -9
  268. reconcile/statuspage/status.py +5 -8
  269. reconcile/templates/rosa-classic-cluster-creation.sh.j2 +5 -1
  270. reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +4 -1
  271. reconcile/templating/lib/merge_request_manager.py +2 -2
  272. reconcile/templating/lib/rendering.py +3 -3
  273. reconcile/templating/renderer.py +12 -13
  274. reconcile/terraform_aws_route53.py +18 -8
  275. reconcile/terraform_cloudflare_dns.py +3 -3
  276. reconcile/terraform_cloudflare_resources.py +12 -13
  277. reconcile/terraform_cloudflare_users.py +3 -2
  278. reconcile/terraform_init/integration.py +187 -23
  279. reconcile/terraform_repo.py +16 -12
  280. reconcile/terraform_resources.py +18 -10
  281. reconcile/terraform_tgw_attachments.py +28 -20
  282. reconcile/terraform_users.py +27 -22
  283. reconcile/terraform_vpc_peerings.py +15 -3
  284. reconcile/terraform_vpc_resources/integration.py +23 -8
  285. reconcile/typed_queries/app_interface_roles.py +10 -0
  286. reconcile/typed_queries/aws_account_tags.py +41 -0
  287. reconcile/typed_queries/cost_report/app_names.py +1 -1
  288. reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
  289. reconcile/typed_queries/saas_files.py +13 -13
  290. reconcile/typed_queries/status_board.py +2 -2
  291. reconcile/unleash_feature_toggles/integration.py +4 -2
  292. reconcile/utils/acs/base.py +6 -3
  293. reconcile/utils/acs/policies.py +2 -2
  294. reconcile/utils/aggregated_list.py +4 -3
  295. reconcile/utils/aws_api.py +51 -20
  296. reconcile/utils/aws_api_typed/api.py +38 -9
  297. reconcile/utils/aws_api_typed/cloudformation.py +149 -0
  298. reconcile/utils/aws_api_typed/logs.py +73 -0
  299. reconcile/utils/aws_api_typed/organization.py +4 -2
  300. reconcile/utils/binary.py +7 -12
  301. reconcile/utils/datetime_util.py +67 -0
  302. reconcile/utils/deadmanssnitch_api.py +1 -1
  303. reconcile/utils/differ.py +2 -3
  304. reconcile/utils/early_exit_cache.py +11 -12
  305. reconcile/utils/expiration.py +7 -3
  306. reconcile/utils/external_resource_spec.py +24 -1
  307. reconcile/utils/filtering.py +1 -1
  308. reconcile/utils/gitlab_api.py +7 -5
  309. reconcile/utils/glitchtip/client.py +6 -2
  310. reconcile/utils/glitchtip/models.py +25 -28
  311. reconcile/utils/gpg.py +5 -3
  312. reconcile/utils/gql.py +4 -7
  313. reconcile/utils/helm.py +2 -1
  314. reconcile/utils/helpers.py +1 -1
  315. reconcile/utils/imap_client.py +1 -1
  316. reconcile/utils/instrumented_wrappers.py +1 -1
  317. reconcile/utils/internal_groups/client.py +2 -2
  318. reconcile/utils/internal_groups/models.py +8 -17
  319. reconcile/utils/jenkins_api.py +24 -1
  320. reconcile/utils/jinja2/utils.py +6 -8
  321. reconcile/utils/jira_client.py +82 -63
  322. reconcile/utils/jjb_client.py +78 -46
  323. reconcile/utils/jobcontroller/controller.py +2 -2
  324. reconcile/utils/jobcontroller/models.py +17 -1
  325. reconcile/utils/json.py +74 -0
  326. reconcile/utils/ldap_client.py +4 -3
  327. reconcile/utils/lean_terraform_client.py +3 -1
  328. reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
  329. reconcile/utils/membershipsources/models.py +16 -23
  330. reconcile/utils/membershipsources/resolver.py +4 -2
  331. reconcile/utils/merge_request_manager/merge_request_manager.py +4 -4
  332. reconcile/utils/merge_request_manager/parser.py +6 -6
  333. reconcile/utils/metrics.py +5 -5
  334. reconcile/utils/models.py +304 -82
  335. reconcile/utils/mr/__init__.py +3 -1
  336. reconcile/utils/mr/app_interface_reporter.py +6 -3
  337. reconcile/utils/mr/aws_access.py +1 -1
  338. reconcile/utils/mr/base.py +7 -13
  339. reconcile/utils/mr/clusters_updates.py +4 -2
  340. reconcile/utils/mr/notificator.py +3 -3
  341. reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py +4 -1
  342. reconcile/utils/mr/promote_qontract.py +28 -12
  343. reconcile/utils/mr/update_access_report_base.py +3 -4
  344. reconcile/utils/mr/user_maintenance.py +7 -6
  345. reconcile/utils/oc.py +445 -336
  346. reconcile/utils/oc_filters.py +3 -3
  347. reconcile/utils/ocm/addons.py +0 -1
  348. reconcile/utils/ocm/base.py +18 -21
  349. reconcile/utils/ocm/cluster_groups.py +1 -1
  350. reconcile/utils/ocm/identity_providers.py +2 -2
  351. reconcile/utils/ocm/labels.py +1 -1
  352. reconcile/utils/ocm/ocm.py +81 -71
  353. reconcile/utils/ocm/products.py +9 -3
  354. reconcile/utils/ocm/search_filters.py +3 -6
  355. reconcile/utils/ocm/service_log.py +4 -6
  356. reconcile/utils/ocm/sre_capability_labels.py +20 -13
  357. reconcile/utils/ocm_base_client.py +4 -4
  358. reconcile/utils/openshift_resource.py +83 -52
  359. reconcile/utils/openssl.py +2 -2
  360. reconcile/utils/output.py +3 -2
  361. reconcile/utils/pagerduty_api.py +10 -7
  362. reconcile/utils/promotion_state.py +6 -11
  363. reconcile/utils/raw_github_api.py +11 -8
  364. reconcile/utils/repo_owners.py +21 -29
  365. reconcile/utils/rhcsv2_certs.py +138 -35
  366. reconcile/utils/rosa/session.py +16 -0
  367. reconcile/utils/runtime/integration.py +2 -3
  368. reconcile/utils/runtime/meta.py +2 -1
  369. reconcile/utils/runtime/runner.py +2 -2
  370. reconcile/utils/saasherder/interfaces.py +13 -20
  371. reconcile/utils/saasherder/models.py +25 -21
  372. reconcile/utils/saasherder/saasherder.py +60 -32
  373. reconcile/utils/secret_reader.py +6 -6
  374. reconcile/utils/sharding.py +1 -1
  375. reconcile/utils/slack_api.py +26 -4
  376. reconcile/utils/sloth.py +224 -0
  377. reconcile/utils/sqs_gateway.py +16 -11
  378. reconcile/utils/state.py +2 -1
  379. reconcile/utils/structs.py +1 -1
  380. reconcile/utils/terraform_client.py +29 -26
  381. reconcile/utils/terrascript_aws_client.py +200 -116
  382. reconcile/utils/three_way_diff_strategy.py +1 -1
  383. reconcile/utils/unleash/server.py +2 -8
  384. reconcile/utils/vault.py +44 -41
  385. reconcile/utils/vcs.py +8 -8
  386. reconcile/vault_replication.py +119 -58
  387. tools/app_interface_reporter.py +4 -4
  388. tools/cli_commands/cost_report/cost_management_api.py +3 -3
  389. tools/cli_commands/cost_report/view.py +7 -6
  390. tools/cli_commands/erv2.py +1 -1
  391. tools/cli_commands/gpg_encrypt.py +4 -1
  392. tools/cli_commands/systems_and_tools.py +5 -1
  393. tools/qontract_cli.py +36 -21
  394. tools/template_validation.py +3 -1
  395. reconcile/gql_definitions/ocm_oidc_idp/__init__.py +0 -0
  396. reconcile/gql_definitions/ocm_subscription_labels/__init__.py +0 -0
  397. reconcile/jenkins/__init__.py +0 -0
  398. reconcile/jenkins/types.py +0 -77
  399. {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/WHEEL +0 -0
  400. {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/entry_points.txt +0 -0
@@ -1,9 +1,8 @@
1
1
  import logging
2
2
  import sys
3
- from collections.abc import Iterable
3
+ from collections.abc import Callable, Iterable
4
4
  from typing import (
5
5
  Any,
6
- cast,
7
6
  )
8
7
 
9
8
  from sretoolbox.utils import threaded
@@ -66,7 +65,6 @@ from reconcile.utils.terrascript.cloudflare_client import (
66
65
  )
67
66
  from reconcile.utils.vault import (
68
67
  VaultClient,
69
- _VaultClient,
70
68
  )
71
69
 
72
70
  QONTRACT_INTEGRATION = "terraform_cloudflare_resources"
@@ -170,7 +168,7 @@ def _build_oc_resources(
170
168
  internal=internal,
171
169
  )
172
170
 
173
- namespace_mapping = [ns.dict() for ns in cloudflare_namespaces]
171
+ namespace_mapping = [ns.model_dump() for ns in cloudflare_namespaces]
174
172
 
175
173
  state_specs = init_specs_to_fetch(
176
174
  ri, oc_map, namespaces=namespace_mapping, override_managed_types=["Secret"]
@@ -193,7 +191,7 @@ def _populate_oc_resources(
193
191
  spec: CurrentStateSpec,
194
192
  ri: ResourceInventory,
195
193
  account_names: Iterable[str] | None,
196
- ):
194
+ ) -> None:
197
195
  """
198
196
  This was taken from terraform_resources and might be a later candidate for DRY.
199
197
  """
@@ -272,7 +270,7 @@ def _write_external_resource_secrets_to_vault(
272
270
  separate module if we have additional needs for a similar function.
273
271
  """
274
272
  integration_name = integration_name.replace("_", "-")
275
- vault_client = cast("_VaultClient", VaultClient())
273
+ vault_client = VaultClient.get_instance()
276
274
  for spec in resource_specs.values():
277
275
  # A secret can be empty if the terraform-* integrations are not enabled on the cluster
278
276
  # the resource is defined on - lets skip vault writes for those right now and
@@ -315,7 +313,7 @@ def run(
315
313
  vault_output_path: str = "",
316
314
  internal: bool | None = None,
317
315
  use_jump_host: bool = True,
318
- defer=None,
316
+ defer: Callable | None = None,
319
317
  ) -> None:
320
318
  vault_settings = get_app_interface_vault_settings()
321
319
  secret_reader = create_secret_reader(use_vault=vault_settings.vault)
@@ -340,7 +338,7 @@ def run(
340
338
  )
341
339
 
342
340
  if not cloudflare_namespaces:
343
- logging.info("No cloudflare namespaces were detected, nothing to do.")
341
+ logging.debug("No cloudflare namespaces were detected, nothing to do.")
344
342
  sys.exit(ExitCodes.SUCCESS)
345
343
 
346
344
  # Build Cloudflare clients
@@ -353,7 +351,7 @@ def run(
353
351
  spec
354
352
  for namespace in query_resources.namespaces
355
353
  for spec in get_external_resource_specs(
356
- namespace.dict(by_alias=True), PROVIDER_CLOUDFLARE
354
+ namespace.model_dump(by_alias=True), PROVIDER_CLOUDFLARE
357
355
  )
358
356
  if not selected_account or spec.provisioner_name == selected_account
359
357
  ]
@@ -385,14 +383,15 @@ def run(
385
383
  QONTRACT_INTEGRATION_VERSION,
386
384
  QONTRACT_TF_PREFIX,
387
385
  [
388
- acct.dict(by_alias=True) # convert CloudflareAccountV1 to dict
386
+ acct.model_dump(by_alias=True) # convert CloudflareAccountV1 to dict
389
387
  for acct in query_accounts.accounts or []
390
388
  if acct.name in cf_clients.dump() # use only if it is a registered client
391
389
  ],
392
390
  working_dirs,
393
391
  thread_pool_size,
394
392
  )
395
- defer(tf.cleanup)
393
+ if defer:
394
+ defer(tf.cleanup)
396
395
 
397
396
  disabled_deletions_detected, err = tf.plan(enable_deletion)
398
397
  if err:
@@ -440,7 +439,7 @@ def _get_cloudflare_desired_state() -> tuple[
440
439
  return query_accounts, query_resources
441
440
 
442
441
 
443
- def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
442
+ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
444
443
  desired_state = _get_cloudflare_desired_state()
445
444
 
446
- 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
  }
@@ -10,7 +10,6 @@ from dataclasses import asdict
10
10
  from typing import (
11
11
  Any,
12
12
  TypedDict,
13
- cast,
14
13
  )
15
14
 
16
15
  from deepdiff import DeepHash
@@ -28,6 +27,7 @@ from reconcile.gql_definitions.terraform_resources.terraform_resources_namespace
28
27
  from reconcile.typed_queries.app_interface_vault_settings import (
29
28
  get_app_interface_vault_settings,
30
29
  )
30
+ from reconcile.typed_queries.external_resources import get_settings
31
31
  from reconcile.typed_queries.terraform_namespaces import get_namespaces
32
32
  from reconcile.utils import gql
33
33
  from reconcile.utils.aws_api import AWSApi
@@ -63,7 +63,6 @@ from reconcile.utils.terrascript_aws_client import TerrascriptClient as Terrascr
63
63
  from reconcile.utils.unleash import get_feature_toggle_state
64
64
  from reconcile.utils.vault import (
65
65
  VaultClient,
66
- _VaultClient,
67
66
  )
68
67
 
69
68
  QONTRACT_INTEGRATION = "terraform_resources"
@@ -138,7 +137,7 @@ def fetch_current_state(
138
137
  use_jump_host=use_jump_host,
139
138
  thread_pool_size=thread_pool_size,
140
139
  )
141
- namespaces_dicts = [ns.dict(by_alias=True) for ns in namespaces]
140
+ namespaces_dicts = [ns.model_dump(by_alias=True) for ns in namespaces]
142
141
  state_specs = ob.init_specs_to_fetch(
143
142
  ri, oc_map, namespaces=namespaces_dicts, override_managed_types=["Secret"]
144
143
  )
@@ -160,6 +159,7 @@ def init_working_dirs(
160
159
  accounts: list[dict[str, Any]],
161
160
  thread_pool_size: int,
162
161
  settings: Mapping[str, Any] | None = None,
162
+ default_tags: Mapping[str, str] | None = None,
163
163
  ) -> tuple[Terrascript, dict[str, str]]:
164
164
  ts = Terrascript(
165
165
  QONTRACT_INTEGRATION,
@@ -167,6 +167,7 @@ def init_working_dirs(
167
167
  thread_pool_size,
168
168
  accounts,
169
169
  settings=settings,
170
+ default_tags=default_tags,
170
171
  )
171
172
  working_dirs = ts.dump()
172
173
  return ts, working_dirs
@@ -243,8 +244,15 @@ def setup(
243
244
  secret_reader = create_secret_reader(use_vault=vault_settings.vault)
244
245
 
245
246
  settings = queries.get_app_interface_settings() or {}
247
+ try:
248
+ default_tags = get_settings().default_tags
249
+ except ValueError:
250
+ # no external resources settings found
251
+ default_tags = None
246
252
  # initialize terrascript (scripting engine to generate terraform manifests)
247
- ts, working_dirs = init_working_dirs(accounts, thread_pool_size, settings=settings)
253
+ ts, working_dirs = init_working_dirs(
254
+ accounts, thread_pool_size, settings=settings, default_tags=default_tags
255
+ )
248
256
 
249
257
  # initialize terraform client
250
258
  # it is used to plan and apply according to the output of terrascript
@@ -265,7 +273,7 @@ def setup(
265
273
  )
266
274
  else:
267
275
  ocm_map = None
268
- 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]
269
277
 
270
278
  provider_exclusions = settings.get("terraformResourcesProviderExclusions") or []
271
279
  ts.init_populate_specs(
@@ -287,16 +295,16 @@ def filter_tf_namespaces(
287
295
  ) -> list[NamespaceV1]:
288
296
  tf_namespaces = []
289
297
  for namespace_info in namespaces:
290
- if ob.is_namespace_deleted(namespace_info.dict(by_alias=True)):
298
+ if ob.is_namespace_deleted(namespace_info.model_dump(by_alias=True)):
291
299
  continue
292
- if not managed_external_resources(namespace_info.dict(by_alias=True)):
300
+ if not managed_external_resources(namespace_info.model_dump(by_alias=True)):
293
301
  continue
294
302
 
295
303
  if not account_names:
296
304
  tf_namespaces.append(namespace_info)
297
305
  continue
298
306
 
299
- specs = get_external_resource_specs(namespace_info.dict(by_alias=True))
307
+ specs = get_external_resource_specs(namespace_info.model_dump(by_alias=True))
300
308
  if not specs:
301
309
  tf_namespaces.append(namespace_info)
302
310
  continue
@@ -314,7 +322,7 @@ def write_outputs_to_vault(
314
322
  vault_path: str, resource_specs: ExternalResourceSpecInventory
315
323
  ) -> None:
316
324
  integration_name = QONTRACT_INTEGRATION.replace("_", "-")
317
- vault_client = cast("_VaultClient", VaultClient())
325
+ vault_client = VaultClient.get_instance()
318
326
  for spec in resource_specs.values():
319
327
  # a secret can be empty if the terraform-integration is not enabled on the cluster
320
328
  # the resource is defined on - lets skip vault writes for those right now and
@@ -559,7 +567,7 @@ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
559
567
  }
560
568
  for ns_info in get_tf_namespaces():
561
569
  for spec in get_external_resource_specs(
562
- ns_info.dict(by_alias=True), provision_provider=PROVIDER_AWS
570
+ ns_info.model_dump(by_alias=True), provision_provider=PROVIDER_AWS
563
571
  ):
564
572
  resource_paths = [
565
573
  spec.resource.get("defaults"),