qontract-reconcile 0.10.2.dev299__py3-none-any.whl → 0.10.2.dev430__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. {qontract_reconcile-0.10.2.dev299.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/METADATA +13 -12
  2. {qontract_reconcile-0.10.2.dev299.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/RECORD +399 -394
  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 +4 -4
  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 +8 -11
  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 +23 -10
  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 +492 -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 +10 -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 +3050 -1393
  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 +448 -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 +5 -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 +4 -0
  270. reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +3 -0
  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 +27 -19
  282. reconcile/terraform_users.py +29 -21
  283. reconcile/terraform_vpc_peerings.py +16 -4
  284. reconcile/terraform_vpc_resources/integration.py +32 -2
  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 +59 -43
  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 +27 -20
  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 +4 -4
  380. reconcile/utils/terraform_client.py +32 -29
  381. reconcile/utils/terrascript_aws_client.py +658 -480
  382. reconcile/utils/three_way_diff_strategy.py +1 -1
  383. reconcile/utils/throughput.py +1 -1
  384. reconcile/utils/unleash/server.py +2 -8
  385. reconcile/utils/vault.py +44 -41
  386. reconcile/utils/vcs.py +8 -8
  387. reconcile/vault_replication.py +119 -58
  388. reconcile/vpc_peerings_validator.py +2 -2
  389. tools/app_interface_reporter.py +4 -4
  390. tools/cli_commands/cost_report/cost_management_api.py +3 -3
  391. tools/cli_commands/cost_report/view.py +7 -6
  392. tools/cli_commands/erv2.py +1 -1
  393. tools/cli_commands/gpg_encrypt.py +4 -1
  394. tools/cli_commands/systems_and_tools.py +5 -1
  395. tools/qontract_cli.py +36 -21
  396. tools/sre_checkpoints/util.py +5 -3
  397. tools/template_validation.py +3 -1
  398. reconcile/gql_definitions/ocm_oidc_idp/__init__.py +0 -0
  399. reconcile/gql_definitions/ocm_subscription_labels/__init__.py +0 -0
  400. reconcile/jenkins/__init__.py +0 -0
  401. reconcile/jenkins/types.py +0 -77
  402. {qontract_reconcile-0.10.2.dev299.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/WHEEL +0 -0
  403. {qontract_reconcile-0.10.2.dev299.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/entry_points.txt +0 -0
@@ -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"),
@@ -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] | 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: