qontract-reconcile 0.10.2.dev349__py3-none-any.whl → 0.10.2.dev414__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 (356) hide show
  1. {qontract_reconcile-0.10.2.dev349.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/METADATA +12 -11
  2. {qontract_reconcile-0.10.2.dev349.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/RECORD +356 -350
  3. reconcile/acs_rbac.py +2 -2
  4. reconcile/aus/advanced_upgrade_service.py +15 -12
  5. reconcile/aus/base.py +26 -27
  6. reconcile/aus/cluster_version_data.py +15 -5
  7. reconcile/aus/models.py +1 -1
  8. reconcile/automated_actions/config/integration.py +15 -3
  9. reconcile/aws_account_manager/integration.py +8 -8
  10. reconcile/aws_account_manager/reconciler.py +3 -3
  11. reconcile/aws_ami_cleanup/integration.py +8 -12
  12. reconcile/aws_ami_share.py +69 -62
  13. reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
  14. reconcile/aws_ecr_image_pull_secrets.py +2 -2
  15. reconcile/aws_iam_keys.py +7 -41
  16. reconcile/aws_saml_idp/integration.py +12 -4
  17. reconcile/aws_saml_roles/integration.py +32 -25
  18. reconcile/aws_version_sync/integration.py +6 -12
  19. reconcile/change_owners/bundle.py +3 -3
  20. reconcile/change_owners/change_log_tracking.py +3 -2
  21. reconcile/change_owners/change_owners.py +1 -1
  22. reconcile/change_owners/diff.py +2 -4
  23. reconcile/checkpoint.py +11 -3
  24. reconcile/cli.py +33 -8
  25. reconcile/dashdotdb_dora.py +5 -12
  26. reconcile/dashdotdb_slo.py +1 -1
  27. reconcile/database_access_manager.py +123 -117
  28. reconcile/dynatrace_token_provider/integration.py +1 -1
  29. reconcile/endpoints_discovery/integration.py +4 -1
  30. reconcile/endpoints_discovery/merge_request.py +1 -1
  31. reconcile/endpoints_discovery/merge_request_manager.py +9 -11
  32. reconcile/external_resources/factories.py +5 -12
  33. reconcile/external_resources/integration.py +1 -1
  34. reconcile/external_resources/manager.py +24 -10
  35. reconcile/external_resources/meta.py +0 -1
  36. reconcile/external_resources/metrics.py +1 -1
  37. reconcile/external_resources/model.py +13 -13
  38. reconcile/external_resources/reconciler.py +7 -4
  39. reconcile/external_resources/secrets_sync.py +6 -8
  40. reconcile/external_resources/state.py +60 -17
  41. reconcile/fleet_labeler/integration.py +1 -1
  42. reconcile/gabi_authorized_users.py +8 -5
  43. reconcile/gcp_image_mirror.py +2 -2
  44. reconcile/github_org.py +1 -1
  45. reconcile/github_owners.py +4 -0
  46. reconcile/gitlab_housekeeping.py +13 -15
  47. reconcile/gitlab_members.py +6 -12
  48. reconcile/gitlab_mr_sqs_consumer.py +2 -2
  49. reconcile/gitlab_owners.py +15 -11
  50. reconcile/gitlab_permissions.py +8 -12
  51. reconcile/glitchtip_project_alerts/integration.py +3 -1
  52. reconcile/gql_definitions/acs/acs_instances.py +5 -5
  53. reconcile/gql_definitions/acs/acs_policies.py +5 -5
  54. reconcile/gql_definitions/acs/acs_rbac.py +5 -5
  55. reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +5 -5
  56. reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +5 -5
  57. reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +5 -5
  58. reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
  59. reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
  60. reconcile/gql_definitions/automated_actions/instance.py +46 -7
  61. reconcile/gql_definitions/aws_account_manager/aws_accounts.py +5 -5
  62. reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +15 -5
  63. reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +27 -66
  64. reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +15 -5
  65. reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +15 -5
  66. reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
  67. reconcile/gql_definitions/aws_version_sync/clusters.py +5 -5
  68. reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
  69. reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
  70. reconcile/gql_definitions/change_owners/queries/self_service_roles.py +5 -5
  71. reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +5 -5
  72. reconcile/gql_definitions/common/alerting_services_settings.py +5 -5
  73. reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
  74. reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
  75. reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
  76. reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
  77. reconcile/gql_definitions/common/app_interface_roles.py +5 -5
  78. reconcile/gql_definitions/common/app_interface_state_settings.py +5 -5
  79. reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
  80. reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
  81. reconcile/gql_definitions/common/apps.py +5 -5
  82. reconcile/gql_definitions/common/aws_vpc_requests.py +15 -5
  83. reconcile/gql_definitions/common/aws_vpcs.py +5 -5
  84. reconcile/gql_definitions/common/clusters.py +7 -5
  85. reconcile/gql_definitions/common/clusters_minimal.py +5 -5
  86. reconcile/gql_definitions/common/clusters_with_dms.py +5 -5
  87. reconcile/gql_definitions/common/clusters_with_peering.py +5 -5
  88. reconcile/gql_definitions/common/github_orgs.py +5 -5
  89. reconcile/gql_definitions/common/jira_settings.py +5 -5
  90. reconcile/gql_definitions/common/jiralert_settings.py +5 -5
  91. reconcile/gql_definitions/common/ldap_settings.py +5 -5
  92. reconcile/gql_definitions/common/namespaces.py +5 -5
  93. reconcile/gql_definitions/common/namespaces_minimal.py +7 -5
  94. reconcile/gql_definitions/common/ocm_env_telemeter.py +5 -5
  95. reconcile/gql_definitions/common/ocm_environments.py +5 -5
  96. reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
  97. reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -5
  98. reconcile/gql_definitions/common/pipeline_providers.py +5 -5
  99. reconcile/gql_definitions/common/quay_instances.py +5 -5
  100. reconcile/gql_definitions/common/quay_orgs.py +5 -5
  101. reconcile/gql_definitions/common/reserved_networks.py +5 -5
  102. reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
  103. reconcile/gql_definitions/common/saas_files.py +5 -5
  104. reconcile/gql_definitions/common/saas_target_namespaces.py +5 -5
  105. reconcile/gql_definitions/common/saasherder_settings.py +5 -5
  106. reconcile/gql_definitions/common/slack_workspaces.py +5 -5
  107. reconcile/gql_definitions/common/smtp_client_settings.py +5 -5
  108. reconcile/gql_definitions/common/state_aws_account.py +5 -5
  109. reconcile/gql_definitions/common/users.py +5 -5
  110. reconcile/gql_definitions/common/users_with_paths.py +5 -5
  111. reconcile/gql_definitions/cost_report/app_names.py +5 -5
  112. reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
  113. reconcile/gql_definitions/cost_report/settings.py +5 -5
  114. reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +5 -5
  115. reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +5 -5
  116. reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
  117. reconcile/gql_definitions/email_sender/apps.py +5 -5
  118. reconcile/gql_definitions/email_sender/emails.py +5 -5
  119. reconcile/gql_definitions/email_sender/users.py +5 -5
  120. reconcile/gql_definitions/endpoints_discovery/apps.py +5 -5
  121. reconcile/gql_definitions/external_resources/aws_accounts.py +5 -5
  122. reconcile/gql_definitions/external_resources/external_resources_modules.py +5 -5
  123. reconcile/gql_definitions/external_resources/external_resources_namespaces.py +89 -6
  124. reconcile/gql_definitions/external_resources/external_resources_settings.py +7 -5
  125. reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
  126. reconcile/gql_definitions/fleet_labeler/fleet_labels.py +5 -5
  127. reconcile/gql_definitions/fragments/aus_organization.py +5 -5
  128. reconcile/gql_definitions/fragments/aws_account_common.py +7 -5
  129. reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
  130. reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
  131. reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
  132. reconcile/gql_definitions/fragments/aws_organization.py +33 -0
  133. reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
  134. reconcile/gql_definitions/fragments/aws_vpc_request.py +7 -5
  135. reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
  136. reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
  137. reconcile/gql_definitions/fragments/disable.py +5 -5
  138. reconcile/gql_definitions/fragments/email_service.py +5 -5
  139. reconcile/gql_definitions/fragments/email_user.py +5 -5
  140. reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
  141. reconcile/gql_definitions/fragments/membership_source.py +5 -5
  142. reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
  143. reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
  144. reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
  145. reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
  146. reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
  147. reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
  148. reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
  149. reconcile/gql_definitions/fragments/resource_values.py +5 -5
  150. reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
  151. reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
  152. reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
  153. reconcile/gql_definitions/fragments/terraform_state.py +5 -5
  154. reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
  155. reconcile/gql_definitions/fragments/user.py +5 -5
  156. reconcile/gql_definitions/fragments/vault_secret.py +5 -5
  157. reconcile/gql_definitions/gcp/gcp_docker_repos.py +5 -5
  158. reconcile/gql_definitions/gcp/gcp_projects.py +5 -5
  159. reconcile/gql_definitions/gitlab_members/gitlab_instances.py +5 -5
  160. reconcile/gql_definitions/gitlab_members/permissions.py +5 -5
  161. reconcile/gql_definitions/glitchtip/glitchtip_instance.py +5 -5
  162. reconcile/gql_definitions/glitchtip/glitchtip_project.py +5 -5
  163. reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +5 -5
  164. reconcile/gql_definitions/integrations/integrations.py +5 -5
  165. reconcile/gql_definitions/introspection.json +2137 -1053
  166. reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +5 -5
  167. reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +5 -5
  168. reconcile/gql_definitions/jira/jira_servers.py +5 -5
  169. reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +9 -5
  170. reconcile/gql_definitions/jumphosts/jumphosts.py +5 -5
  171. reconcile/gql_definitions/ldap_groups/roles.py +5 -5
  172. reconcile/gql_definitions/ldap_groups/settings.py +5 -5
  173. reconcile/gql_definitions/maintenance/maintenances.py +5 -5
  174. reconcile/gql_definitions/membershipsources/roles.py +5 -5
  175. reconcile/gql_definitions/ocm_labels/clusters.py +5 -5
  176. reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
  177. reconcile/gql_definitions/openshift_cluster_bots/clusters.py +5 -5
  178. reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
  179. reconcile/gql_definitions/openshift_groups/managed_roles.py +5 -5
  180. reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +5 -5
  181. reconcile/gql_definitions/quay_membership/quay_membership.py +5 -5
  182. reconcile/gql_definitions/rhcs/certs.py +5 -5
  183. reconcile/gql_definitions/rhidp/organizations.py +5 -5
  184. reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
  185. reconcile/gql_definitions/service_dependencies/service_dependencies.py +5 -5
  186. reconcile/gql_definitions/sharding/aws_accounts.py +5 -5
  187. reconcile/gql_definitions/sharding/ocm_organization.py +5 -5
  188. reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
  189. reconcile/gql_definitions/skupper_network/skupper_networks.py +5 -5
  190. reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
  191. reconcile/gql_definitions/slack_usergroups/permissions.py +5 -5
  192. reconcile/gql_definitions/slack_usergroups/users.py +5 -5
  193. reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
  194. reconcile/gql_definitions/status_board/status_board.py +5 -5
  195. reconcile/gql_definitions/statuspage/statuspages.py +5 -5
  196. reconcile/gql_definitions/templating/template_collection.py +5 -5
  197. reconcile/gql_definitions/templating/templates.py +5 -5
  198. reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +5 -5
  199. reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +5 -5
  200. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +5 -5
  201. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +5 -5
  202. reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +5 -5
  203. reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +5 -5
  204. reconcile/gql_definitions/terraform_init/aws_accounts.py +19 -5
  205. reconcile/gql_definitions/terraform_repo/terraform_repo.py +5 -5
  206. reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
  207. reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +38 -6
  208. reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +15 -5
  209. reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +5 -5
  210. reconcile/gql_definitions/vault_instances/vault_instances.py +5 -5
  211. reconcile/gql_definitions/vault_policies/vault_policies.py +5 -5
  212. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +5 -5
  213. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
  214. reconcile/integrations_manager.py +3 -3
  215. reconcile/jenkins_worker_fleets.py +10 -8
  216. reconcile/jira_permissions_validator.py +237 -122
  217. reconcile/ldap_groups/integration.py +1 -1
  218. reconcile/ocm/types.py +35 -56
  219. reconcile/ocm_aws_infrastructure_access.py +1 -1
  220. reconcile/ocm_clusters.py +4 -4
  221. reconcile/ocm_labels/integration.py +3 -2
  222. reconcile/ocm_machine_pools.py +23 -23
  223. reconcile/openshift_base.py +53 -2
  224. reconcile/openshift_cluster_bots.py +3 -2
  225. reconcile/openshift_namespace_labels.py +1 -1
  226. reconcile/openshift_namespaces.py +97 -101
  227. reconcile/openshift_resources_base.py +6 -2
  228. reconcile/openshift_rhcs_certs.py +5 -5
  229. reconcile/openshift_rolebindings.py +7 -11
  230. reconcile/openshift_saas_deploy.py +6 -7
  231. reconcile/openshift_saas_deploy_change_tester.py +9 -7
  232. reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
  233. reconcile/openshift_serviceaccount_tokens.py +2 -2
  234. reconcile/openshift_upgrade_watcher.py +4 -4
  235. reconcile/oum/labelset.py +5 -3
  236. reconcile/oum/models.py +1 -4
  237. reconcile/prometheus_rules_tester/integration.py +3 -3
  238. reconcile/quay_mirror.py +1 -1
  239. reconcile/queries.py +131 -1
  240. reconcile/rhidp/common.py +3 -5
  241. reconcile/rhidp/sso_client/base.py +1 -1
  242. reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
  243. reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
  244. reconcile/skupper_network/integration.py +2 -2
  245. reconcile/slack_usergroups.py +35 -14
  246. reconcile/sql_query.py +1 -0
  247. reconcile/status_board.py +6 -6
  248. reconcile/statuspage/atlassian.py +7 -7
  249. reconcile/statuspage/integrations/maintenances.py +4 -3
  250. reconcile/statuspage/page.py +4 -9
  251. reconcile/statuspage/status.py +5 -8
  252. reconcile/templates/rosa-classic-cluster-creation.sh.j2 +4 -0
  253. reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +3 -0
  254. reconcile/templating/lib/rendering.py +3 -3
  255. reconcile/templating/renderer.py +4 -3
  256. reconcile/terraform_aws_route53.py +7 -1
  257. reconcile/terraform_cloudflare_dns.py +3 -3
  258. reconcile/terraform_cloudflare_resources.py +5 -5
  259. reconcile/terraform_cloudflare_users.py +3 -2
  260. reconcile/terraform_init/integration.py +187 -23
  261. reconcile/terraform_repo.py +16 -12
  262. reconcile/terraform_resources.py +17 -7
  263. reconcile/terraform_tgw_attachments.py +27 -19
  264. reconcile/terraform_users.py +7 -0
  265. reconcile/terraform_vpc_peerings.py +14 -3
  266. reconcile/terraform_vpc_resources/integration.py +10 -1
  267. reconcile/typed_queries/aws_account_tags.py +41 -0
  268. reconcile/typed_queries/cost_report/app_names.py +1 -1
  269. reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
  270. reconcile/typed_queries/saas_files.py +13 -13
  271. reconcile/typed_queries/status_board.py +2 -2
  272. reconcile/unleash_feature_toggles/integration.py +4 -2
  273. reconcile/utils/acs/base.py +6 -3
  274. reconcile/utils/acs/policies.py +2 -2
  275. reconcile/utils/aggregated_list.py +4 -3
  276. reconcile/utils/aws_api.py +51 -54
  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/datetime_util.py +67 -0
  282. reconcile/utils/deadmanssnitch_api.py +1 -1
  283. reconcile/utils/differ.py +2 -3
  284. reconcile/utils/early_exit_cache.py +11 -12
  285. reconcile/utils/expiration.py +7 -3
  286. reconcile/utils/external_resource_spec.py +24 -1
  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/helm.py +2 -1
  293. reconcile/utils/helpers.py +1 -1
  294. reconcile/utils/instrumented_wrappers.py +1 -1
  295. reconcile/utils/internal_groups/client.py +2 -2
  296. reconcile/utils/internal_groups/models.py +8 -17
  297. reconcile/utils/jinja2/utils.py +6 -101
  298. reconcile/utils/jira_client.py +82 -63
  299. reconcile/utils/jjb_client.py +9 -12
  300. reconcile/utils/jobcontroller/controller.py +1 -1
  301. reconcile/utils/jobcontroller/models.py +17 -1
  302. reconcile/utils/json.py +70 -0
  303. reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
  304. reconcile/utils/membershipsources/models.py +16 -23
  305. reconcile/utils/membershipsources/resolver.py +4 -2
  306. reconcile/utils/merge_request_manager/merge_request_manager.py +4 -4
  307. reconcile/utils/merge_request_manager/parser.py +6 -6
  308. reconcile/utils/metrics.py +5 -5
  309. reconcile/utils/models.py +304 -82
  310. reconcile/utils/mr/app_interface_reporter.py +2 -2
  311. reconcile/utils/mr/base.py +2 -2
  312. reconcile/utils/mr/notificator.py +3 -3
  313. reconcile/utils/mr/update_access_report_base.py +3 -4
  314. reconcile/utils/mr/user_maintenance.py +3 -2
  315. reconcile/utils/oc.py +118 -97
  316. reconcile/utils/oc_filters.py +3 -3
  317. reconcile/utils/ocm/addons.py +0 -1
  318. reconcile/utils/ocm/base.py +17 -20
  319. reconcile/utils/ocm/cluster_groups.py +1 -1
  320. reconcile/utils/ocm/identity_providers.py +2 -2
  321. reconcile/utils/ocm/labels.py +1 -1
  322. reconcile/utils/ocm/products.py +9 -3
  323. reconcile/utils/ocm/search_filters.py +3 -6
  324. reconcile/utils/ocm/service_log.py +4 -6
  325. reconcile/utils/ocm/sre_capability_labels.py +20 -13
  326. reconcile/utils/openshift_resource.py +10 -5
  327. reconcile/utils/output.py +3 -2
  328. reconcile/utils/pagerduty_api.py +10 -7
  329. reconcile/utils/promotion_state.py +6 -11
  330. reconcile/utils/raw_github_api.py +1 -1
  331. reconcile/utils/rhcsv2_certs.py +1 -4
  332. reconcile/utils/runtime/integration.py +2 -3
  333. reconcile/utils/runtime/runner.py +2 -2
  334. reconcile/utils/saasherder/interfaces.py +13 -20
  335. reconcile/utils/saasherder/models.py +25 -21
  336. reconcile/utils/saasherder/saasherder.py +35 -24
  337. reconcile/utils/slack_api.py +26 -4
  338. reconcile/utils/sloth.py +171 -2
  339. reconcile/utils/sqs_gateway.py +2 -1
  340. reconcile/utils/state.py +2 -1
  341. reconcile/utils/structs.py +1 -1
  342. reconcile/utils/terraform_client.py +5 -4
  343. reconcile/utils/terrascript_aws_client.py +171 -114
  344. reconcile/utils/unleash/server.py +2 -8
  345. reconcile/utils/vault.py +5 -12
  346. reconcile/utils/vcs.py +8 -8
  347. reconcile/vault_replication.py +107 -42
  348. tools/app_interface_reporter.py +4 -4
  349. tools/cli_commands/cost_report/cost_management_api.py +3 -3
  350. tools/cli_commands/cost_report/view.py +7 -6
  351. tools/cli_commands/erv2.py +3 -1
  352. tools/cli_commands/systems_and_tools.py +5 -1
  353. tools/qontract_cli.py +31 -18
  354. tools/template_validation.py +3 -1
  355. {qontract_reconcile-0.10.2.dev349.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/WHEEL +0 -0
  356. {qontract_reconcile-0.10.2.dev349.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/entry_points.txt +0 -0
@@ -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
  }
@@ -27,6 +27,7 @@ from reconcile.gql_definitions.terraform_resources.terraform_resources_namespace
27
27
  from reconcile.typed_queries.app_interface_vault_settings import (
28
28
  get_app_interface_vault_settings,
29
29
  )
30
+ from reconcile.typed_queries.external_resources import get_settings
30
31
  from reconcile.typed_queries.terraform_namespaces import get_namespaces
31
32
  from reconcile.utils import gql
32
33
  from reconcile.utils.aws_api import AWSApi
@@ -136,7 +137,7 @@ def fetch_current_state(
136
137
  use_jump_host=use_jump_host,
137
138
  thread_pool_size=thread_pool_size,
138
139
  )
139
- namespaces_dicts = [ns.dict(by_alias=True) for ns in namespaces]
140
+ namespaces_dicts = [ns.model_dump(by_alias=True) for ns in namespaces]
140
141
  state_specs = ob.init_specs_to_fetch(
141
142
  ri, oc_map, namespaces=namespaces_dicts, override_managed_types=["Secret"]
142
143
  )
@@ -158,6 +159,7 @@ def init_working_dirs(
158
159
  accounts: list[dict[str, Any]],
159
160
  thread_pool_size: int,
160
161
  settings: Mapping[str, Any] | None = None,
162
+ default_tags: Mapping[str, str] | None = None,
161
163
  ) -> tuple[Terrascript, dict[str, str]]:
162
164
  ts = Terrascript(
163
165
  QONTRACT_INTEGRATION,
@@ -165,6 +167,7 @@ def init_working_dirs(
165
167
  thread_pool_size,
166
168
  accounts,
167
169
  settings=settings,
170
+ default_tags=default_tags,
168
171
  )
169
172
  working_dirs = ts.dump()
170
173
  return ts, working_dirs
@@ -241,8 +244,15 @@ def setup(
241
244
  secret_reader = create_secret_reader(use_vault=vault_settings.vault)
242
245
 
243
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
244
252
  # initialize terrascript (scripting engine to generate terraform manifests)
245
- 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
+ )
246
256
 
247
257
  # initialize terraform client
248
258
  # it is used to plan and apply according to the output of terrascript
@@ -263,7 +273,7 @@ def setup(
263
273
  )
264
274
  else:
265
275
  ocm_map = None
266
- 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]
267
277
 
268
278
  provider_exclusions = settings.get("terraformResourcesProviderExclusions") or []
269
279
  ts.init_populate_specs(
@@ -285,16 +295,16 @@ def filter_tf_namespaces(
285
295
  ) -> list[NamespaceV1]:
286
296
  tf_namespaces = []
287
297
  for namespace_info in namespaces:
288
- if ob.is_namespace_deleted(namespace_info.dict(by_alias=True)):
298
+ if ob.is_namespace_deleted(namespace_info.model_dump(by_alias=True)):
289
299
  continue
290
- if not managed_external_resources(namespace_info.dict(by_alias=True)):
300
+ if not managed_external_resources(namespace_info.model_dump(by_alias=True)):
291
301
  continue
292
302
 
293
303
  if not account_names:
294
304
  tf_namespaces.append(namespace_info)
295
305
  continue
296
306
 
297
- specs = get_external_resource_specs(namespace_info.dict(by_alias=True))
307
+ specs = get_external_resource_specs(namespace_info.model_dump(by_alias=True))
298
308
  if not specs:
299
309
  tf_namespaces.append(namespace_info)
300
310
  continue
@@ -557,7 +567,7 @@ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
557
567
  }
558
568
  for ns_info in get_tf_namespaces():
559
569
  for spec in get_external_resource_specs(
560
- ns_info.dict(by_alias=True), provision_provider=PROVIDER_AWS
570
+ ns_info.model_dump(by_alias=True), provision_provider=PROVIDER_AWS
561
571
  ):
562
572
  resource_paths = [
563
573
  spec.resource.get("defaults"),
@@ -32,6 +32,7 @@ from reconcile.typed_queries.app_interface_vault_settings import (
32
32
  get_app_interface_vault_settings,
33
33
  )
34
34
  from reconcile.typed_queries.clusters_with_peering import get_clusters_with_peering
35
+ from reconcile.typed_queries.external_resources import get_settings
35
36
  from reconcile.typed_queries.terraform_tgw_attachments.aws_accounts import (
36
37
  get_aws_accounts,
37
38
  )
@@ -68,7 +69,7 @@ class ValidationError(Exception):
68
69
  class TGWAccountProviderInfo(BaseModel):
69
70
  name: str
70
71
  uid: str
71
- assume_role: str | None
72
+ assume_role: str | None = None
72
73
  assume_region: str
73
74
 
74
75
 
@@ -80,10 +81,10 @@ class Requester(BaseModel):
80
81
  tgw_id: str
81
82
  tgw_arn: str
82
83
  region: str
83
- routes: list[dict] | None
84
- rules: list[dict] | None
85
- hostedzones: list[str] | None
86
- cidr_block: str | None
84
+ routes: list[dict] | None = None
85
+ rules: list[dict] | None = None
86
+ hostedzones: list[str] | None = None
87
+ cidr_block: str | None = None
87
88
  cidr_blocks: list[str]
88
89
  account: TGWAccountProviderInfo
89
90
 
@@ -91,11 +92,11 @@ class Requester(BaseModel):
91
92
  class Accepter(BaseModel):
92
93
  cidr_block: str
93
94
  region: str
94
- vpc_id: str | None
95
- route_table_ids: list[str] | None
96
- subnets_id_az: list[dict[str, str]] | None
95
+ vpc_id: str | None = None
96
+ route_table_ids: list[str] | None = None
97
+ subnets_id_az: list[dict[str, str]] | None = None
97
98
  account: ClusterAccountProviderInfo
98
- api_security_group_id: str | None
99
+ api_security_group_id: str | None = None
99
100
 
100
101
 
101
102
  class DesiredStateItem(BaseModel):
@@ -192,7 +193,7 @@ def _build_desired_state_tgw_connection(
192
193
  yield None
193
194
 
194
195
  account_tgws = awsapi.get_tgws_details(
195
- peer_connection.account.dict(by_alias=True),
196
+ peer_connection.account.model_dump(by_alias=True),
196
197
  cluster_region,
197
198
  cluster_cidr_block,
198
199
  tags=peer_connection.tags or {},
@@ -274,7 +275,7 @@ def _build_accepter(
274
275
  )
275
276
  (vpc_id, route_table_ids, subnets_id_az, api_security_group_id) = (
276
277
  awsapi.get_cluster_vpc_details(
277
- account.dict(by_alias=True),
278
+ account.model_dump(by_alias=True),
278
279
  route_tables=bool(peer_connection.manage_routes),
279
280
  subnets=True,
280
281
  hcp_vpc_endpoint_sg=allow_hcp_private_api_access,
@@ -317,12 +318,12 @@ def _build_ocm_map(
317
318
  clusters: Iterable[ClusterV1],
318
319
  vault_settings: AppInterfaceSettingsV1,
319
320
  ) -> OCMMap | None:
320
- ocm_clusters = [c.dict(by_alias=True) for c in clusters if c.ocm]
321
+ ocm_clusters = [c.model_dump(by_alias=True) for c in clusters if c.ocm]
321
322
  return (
322
323
  OCMMap(
323
324
  clusters=ocm_clusters,
324
325
  integration=QONTRACT_INTEGRATION,
325
- settings=vault_settings.dict(by_alias=True),
326
+ settings=vault_settings.model_dump(by_alias=True),
326
327
  )
327
328
  if ocm_clusters
328
329
  # this is a case for an OCP cluster which is not provisioned
@@ -346,7 +347,7 @@ def _populate_tgw_attachments_working_dirs(
346
347
  accounts_by_infra_account_name: dict[str, list[dict[str, Any]]] = {}
347
348
  for item in desired_state:
348
349
  accounts_by_infra_account_name.setdefault(item.infra_acount_name, []).append(
349
- item.accepter.account.dict(by_alias=True)
350
+ item.accepter.account.model_dump(by_alias=True)
350
351
  )
351
352
  for infra_account_name, accounts in accounts_by_infra_account_name.items():
352
353
  ts.populate_additional_providers(infra_account_name, accounts)
@@ -428,7 +429,9 @@ def setup(
428
429
  print_to_file: str | None = None,
429
430
  ) -> tuple[SecretReaderBase, AWSApi, Terraform, Terrascript]:
430
431
  tgw_clusters = desired_state_data_source.clusters
431
- all_accounts = [a.dict(by_alias=True) for a in desired_state_data_source.accounts]
432
+ all_accounts = [
433
+ a.model_dump(by_alias=True) for a in desired_state_data_source.accounts
434
+ ]
432
435
  account_by_name = {a["name"]: a for a in all_accounts}
433
436
  vault_settings = get_app_interface_vault_settings()
434
437
  secret_reader = create_secret_reader(vault_settings.vault)
@@ -444,13 +447,18 @@ def setup(
444
447
  raise RuntimeError("Could not find VPC ID for cluster")
445
448
 
446
449
  _validate_tgw_connection_names(desired_state)
447
-
450
+ try:
451
+ default_tags = get_settings().default_tags
452
+ except ValueError:
453
+ # no external resources settings found
454
+ default_tags = None
448
455
  ts = Terrascript(
449
456
  QONTRACT_INTEGRATION,
450
457
  "",
451
458
  thread_pool_size,
452
459
  tgw_accounts,
453
- settings=vault_settings.dict(by_alias=True),
460
+ settings=vault_settings.model_dump(by_alias=True),
461
+ default_tags=default_tags,
454
462
  )
455
463
  tgw_rosa_cluster_accounts = [
456
464
  account_by_name[c.spec.account.name]
@@ -510,7 +518,7 @@ def run(
510
518
  ) -> None:
511
519
  desired_state_data_source = _fetch_desired_state_data_source(account_name)
512
520
  tgw_accounts = [
513
- a.dict(by_alias=True)
521
+ a.model_dump(by_alias=True)
514
522
  for a in _filter_tgw_accounts(
515
523
  desired_state_data_source.accounts, desired_state_data_source.clusters
516
524
  )
@@ -567,7 +575,7 @@ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
567
575
  desired_state = _fetch_desired_state_data_source()
568
576
  for a in desired_state.accounts:
569
577
  a.deletion_approvals = []
570
- return desired_state.dict(by_alias=True)
578
+ return desired_state.model_dump(by_alias=True)
571
579
 
572
580
 
573
581
  def desired_state_shard_config() -> DesiredStateShardConfig:
@@ -11,6 +11,7 @@ from reconcile import (
11
11
  )
12
12
  from reconcile.change_owners.diff import IDENTIFIER_FIELD_NAME
13
13
  from reconcile.gql_definitions.common.pgp_reencryption_settings import query
14
+ from reconcile.typed_queries.external_resources import get_settings
14
15
  from reconcile.utils import (
15
16
  expiration,
16
17
  gql,
@@ -126,12 +127,18 @@ def setup(
126
127
  participating_aws_accounts = _filter_participating_aws_accounts(accounts, roles)
127
128
 
128
129
  settings = queries.get_app_interface_settings()
130
+ try:
131
+ default_tags = get_settings().default_tags
132
+ except ValueError:
133
+ # no external resources settings found
134
+ default_tags = None
129
135
  ts = Terrascript(
130
136
  QONTRACT_INTEGRATION,
131
137
  QONTRACT_TF_PREFIX,
132
138
  thread_pool_size,
133
139
  participating_aws_accounts,
134
140
  settings=settings,
141
+ default_tags=default_tags,
135
142
  )
136
143
  err = ts.populate_users(
137
144
  roles,
@@ -7,6 +7,7 @@ from typing import Any, TypedDict
7
7
  import reconcile.utils.terraform_client as terraform
8
8
  import reconcile.utils.terrascript_aws_client as terrascript
9
9
  from reconcile import queries
10
+ from reconcile.typed_queries import external_resources
10
11
  from reconcile.utils import (
11
12
  aws_api,
12
13
  ocm,
@@ -654,8 +655,18 @@ def run(
654
655
  ])
655
656
 
656
657
  account_by_name = {a["name"]: a for a in accounts}
658
+ try:
659
+ default_tags = external_resources.get_settings().default_tags
660
+ except ValueError:
661
+ # no external resources settings found
662
+ default_tags = None
657
663
  with terrascript.TerrascriptClient(
658
- QONTRACT_INTEGRATION, "", thread_pool_size, infra_accounts, settings=settings
664
+ QONTRACT_INTEGRATION,
665
+ "",
666
+ thread_pool_size,
667
+ infra_accounts,
668
+ settings=settings,
669
+ default_tags=default_tags,
659
670
  ) as ts:
660
671
  rosa_cluster_accounts = [
661
672
  account_by_name[c["spec"]["account"]["name"]]
@@ -664,8 +675,8 @@ def run(
664
675
  ]
665
676
  ts.populate_configs(rosa_cluster_accounts)
666
677
 
667
- for infra_account_name, items in participating_accounts.items():
668
- ts.populate_additional_providers(infra_account_name, items)
678
+ for infra_account_name, accounts in participating_accounts.items():
679
+ ts.populate_additional_providers(infra_account_name, accounts)
669
680
  ts.populate_vpc_peerings(desired_state)
670
681
  working_dirs = ts.dump(print_to_file=print_to_file)
671
682
  terraform_configurations = ts.terraform_configurations()