qontract-reconcile 0.10.2.dev310__py3-none-any.whl → 0.10.2.dev439__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (400) hide show
  1. {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/METADATA +13 -12
  2. {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/RECORD +396 -391
  3. reconcile/acs_rbac.py +2 -2
  4. reconcile/aus/advanced_upgrade_service.py +18 -12
  5. reconcile/aus/base.py +134 -32
  6. reconcile/aus/cluster_version_data.py +15 -5
  7. reconcile/aus/models.py +3 -1
  8. reconcile/aus/ocm_addons_upgrade_scheduler_org.py +1 -0
  9. reconcile/aus/ocm_upgrade_scheduler.py +8 -1
  10. reconcile/aus/ocm_upgrade_scheduler_org.py +20 -5
  11. reconcile/aus/version_gates/sts_version_gate_handler.py +54 -1
  12. reconcile/automated_actions/config/integration.py +16 -4
  13. reconcile/aws_account_manager/integration.py +8 -8
  14. reconcile/aws_account_manager/reconciler.py +3 -3
  15. reconcile/aws_ami_cleanup/integration.py +8 -12
  16. reconcile/aws_ami_share.py +69 -62
  17. reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
  18. reconcile/aws_ecr_image_pull_secrets.py +5 -5
  19. reconcile/aws_iam_keys.py +1 -0
  20. reconcile/aws_saml_idp/integration.py +12 -4
  21. reconcile/aws_saml_roles/integration.py +32 -25
  22. reconcile/aws_version_sync/integration.py +125 -84
  23. reconcile/change_owners/bundle.py +3 -3
  24. reconcile/change_owners/change_log_tracking.py +3 -2
  25. reconcile/change_owners/change_owners.py +1 -1
  26. reconcile/change_owners/diff.py +2 -4
  27. reconcile/checkpoint.py +12 -4
  28. reconcile/cli.py +111 -18
  29. reconcile/cluster_deployment_mapper.py +2 -3
  30. reconcile/dashdotdb_dora.py +5 -12
  31. reconcile/dashdotdb_slo.py +1 -1
  32. reconcile/database_access_manager.py +125 -121
  33. reconcile/deadmanssnitch.py +1 -5
  34. reconcile/dynatrace_token_provider/integration.py +1 -1
  35. reconcile/endpoints_discovery/integration.py +4 -1
  36. reconcile/endpoints_discovery/merge_request.py +1 -1
  37. reconcile/endpoints_discovery/merge_request_manager.py +9 -11
  38. reconcile/external_resources/factories.py +5 -12
  39. reconcile/external_resources/integration.py +1 -1
  40. reconcile/external_resources/manager.py +8 -5
  41. reconcile/external_resources/meta.py +0 -1
  42. reconcile/external_resources/metrics.py +1 -1
  43. reconcile/external_resources/model.py +20 -20
  44. reconcile/external_resources/reconciler.py +7 -4
  45. reconcile/external_resources/secrets_sync.py +10 -14
  46. reconcile/external_resources/state.py +26 -16
  47. reconcile/fleet_labeler/integration.py +1 -1
  48. reconcile/gabi_authorized_users.py +8 -5
  49. reconcile/gcp_image_mirror.py +2 -2
  50. reconcile/github_org.py +1 -1
  51. reconcile/github_owners.py +4 -0
  52. reconcile/gitlab_housekeeping.py +13 -15
  53. reconcile/gitlab_members.py +6 -12
  54. reconcile/gitlab_mr_sqs_consumer.py +2 -2
  55. reconcile/gitlab_owners.py +15 -11
  56. reconcile/gitlab_permissions.py +8 -12
  57. reconcile/glitchtip_project_alerts/integration.py +3 -1
  58. reconcile/gql_definitions/acs/acs_instances.py +10 -10
  59. reconcile/gql_definitions/acs/acs_policies.py +5 -5
  60. reconcile/gql_definitions/acs/acs_rbac.py +6 -6
  61. reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +32 -32
  62. reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +26 -26
  63. reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +6 -7
  64. reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
  65. reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
  66. reconcile/gql_definitions/automated_actions/instance.py +51 -12
  67. reconcile/gql_definitions/aws_account_manager/aws_accounts.py +11 -11
  68. reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +20 -10
  69. reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +28 -68
  70. reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +20 -10
  71. reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +20 -10
  72. reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
  73. reconcile/gql_definitions/aws_version_sync/clusters.py +10 -10
  74. reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
  75. reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
  76. reconcile/gql_definitions/change_owners/queries/self_service_roles.py +9 -9
  77. reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +18 -18
  78. reconcile/gql_definitions/common/alerting_services_settings.py +9 -9
  79. reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
  80. reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
  81. reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
  82. reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
  83. reconcile/gql_definitions/common/app_interface_roles.py +120 -0
  84. reconcile/gql_definitions/common/app_interface_state_settings.py +10 -10
  85. reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
  86. reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
  87. reconcile/gql_definitions/common/apps.py +5 -5
  88. reconcile/gql_definitions/common/aws_vpc_requests.py +22 -9
  89. reconcile/gql_definitions/common/aws_vpcs.py +11 -11
  90. reconcile/gql_definitions/common/clusters.py +37 -35
  91. reconcile/gql_definitions/common/clusters_minimal.py +14 -14
  92. reconcile/gql_definitions/common/clusters_with_dms.py +6 -6
  93. reconcile/gql_definitions/common/clusters_with_peering.py +29 -30
  94. reconcile/gql_definitions/common/github_orgs.py +10 -10
  95. reconcile/gql_definitions/common/jira_settings.py +10 -10
  96. reconcile/gql_definitions/common/jiralert_settings.py +5 -5
  97. reconcile/gql_definitions/common/ldap_settings.py +5 -5
  98. reconcile/gql_definitions/common/namespaces.py +42 -44
  99. reconcile/gql_definitions/common/namespaces_minimal.py +15 -13
  100. reconcile/gql_definitions/common/ocm_env_telemeter.py +12 -12
  101. reconcile/gql_definitions/common/ocm_environments.py +19 -19
  102. reconcile/gql_definitions/common/pagerduty_instances.py +9 -9
  103. reconcile/gql_definitions/common/pgp_reencryption_settings.py +6 -6
  104. reconcile/gql_definitions/common/pipeline_providers.py +29 -29
  105. reconcile/gql_definitions/common/quay_instances.py +5 -5
  106. reconcile/gql_definitions/common/quay_orgs.py +5 -5
  107. reconcile/gql_definitions/common/reserved_networks.py +5 -5
  108. reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
  109. reconcile/gql_definitions/common/saas_files.py +44 -44
  110. reconcile/gql_definitions/common/saas_target_namespaces.py +10 -10
  111. reconcile/gql_definitions/common/saasherder_settings.py +5 -5
  112. reconcile/gql_definitions/common/slack_workspaces.py +5 -5
  113. reconcile/gql_definitions/common/smtp_client_settings.py +19 -19
  114. reconcile/gql_definitions/common/state_aws_account.py +7 -8
  115. reconcile/gql_definitions/common/users.py +5 -5
  116. reconcile/gql_definitions/common/users_with_paths.py +5 -5
  117. reconcile/gql_definitions/cost_report/app_names.py +5 -5
  118. reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
  119. reconcile/gql_definitions/cost_report/settings.py +9 -9
  120. reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +43 -43
  121. reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +10 -10
  122. reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
  123. reconcile/gql_definitions/email_sender/apps.py +5 -5
  124. reconcile/gql_definitions/email_sender/emails.py +8 -8
  125. reconcile/gql_definitions/email_sender/users.py +6 -6
  126. reconcile/gql_definitions/endpoints_discovery/apps.py +10 -10
  127. reconcile/gql_definitions/external_resources/aws_accounts.py +9 -9
  128. reconcile/gql_definitions/external_resources/external_resources_modules.py +23 -23
  129. reconcile/gql_definitions/external_resources/external_resources_namespaces.py +494 -410
  130. reconcile/gql_definitions/external_resources/external_resources_settings.py +28 -26
  131. reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
  132. reconcile/gql_definitions/fleet_labeler/fleet_labels.py +40 -40
  133. reconcile/gql_definitions/fragments/aus_organization.py +5 -5
  134. reconcile/gql_definitions/fragments/aws_account_common.py +7 -5
  135. reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
  136. reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
  137. reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
  138. reconcile/gql_definitions/fragments/{aws_vpc_request_subnet.py → aws_organization.py} +12 -8
  139. reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
  140. reconcile/gql_definitions/fragments/aws_vpc_request.py +12 -5
  141. reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
  142. reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
  143. reconcile/gql_definitions/fragments/disable.py +5 -5
  144. reconcile/gql_definitions/fragments/email_service.py +5 -5
  145. reconcile/gql_definitions/fragments/email_user.py +5 -5
  146. reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
  147. reconcile/gql_definitions/fragments/membership_source.py +5 -5
  148. reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
  149. reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
  150. reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
  151. reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
  152. reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
  153. reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
  154. reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
  155. reconcile/gql_definitions/fragments/resource_values.py +5 -5
  156. reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
  157. reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
  158. reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
  159. reconcile/gql_definitions/fragments/terraform_state.py +5 -5
  160. reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
  161. reconcile/gql_definitions/fragments/user.py +5 -5
  162. reconcile/gql_definitions/fragments/vault_secret.py +5 -5
  163. reconcile/gql_definitions/gcp/gcp_docker_repos.py +9 -9
  164. reconcile/gql_definitions/gcp/gcp_projects.py +9 -9
  165. reconcile/gql_definitions/gitlab_members/gitlab_instances.py +9 -9
  166. reconcile/gql_definitions/gitlab_members/permissions.py +9 -9
  167. reconcile/gql_definitions/glitchtip/glitchtip_instance.py +9 -9
  168. reconcile/gql_definitions/glitchtip/glitchtip_project.py +11 -11
  169. reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +9 -9
  170. reconcile/gql_definitions/integrations/integrations.py +48 -51
  171. reconcile/gql_definitions/introspection.json +3510 -1865
  172. reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +11 -11
  173. reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +10 -10
  174. reconcile/gql_definitions/jira/jira_servers.py +5 -5
  175. reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +14 -10
  176. reconcile/gql_definitions/jumphosts/jumphosts.py +13 -13
  177. reconcile/gql_definitions/ldap_groups/roles.py +5 -5
  178. reconcile/gql_definitions/ldap_groups/settings.py +9 -9
  179. reconcile/gql_definitions/maintenance/maintenances.py +5 -5
  180. reconcile/gql_definitions/membershipsources/roles.py +5 -5
  181. reconcile/gql_definitions/ocm_labels/clusters.py +18 -19
  182. reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
  183. reconcile/gql_definitions/openshift_cluster_bots/clusters.py +22 -22
  184. reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
  185. reconcile/gql_definitions/openshift_groups/managed_roles.py +6 -6
  186. reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +10 -10
  187. reconcile/gql_definitions/quay_membership/quay_membership.py +6 -6
  188. reconcile/gql_definitions/rhcs/certs.py +33 -87
  189. reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
  190. reconcile/gql_definitions/rhidp/organizations.py +18 -18
  191. reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
  192. reconcile/gql_definitions/service_dependencies/service_dependencies.py +8 -8
  193. reconcile/gql_definitions/sharding/aws_accounts.py +10 -10
  194. reconcile/gql_definitions/sharding/ocm_organization.py +8 -8
  195. reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
  196. reconcile/gql_definitions/skupper_network/skupper_networks.py +10 -10
  197. reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
  198. reconcile/gql_definitions/slack_usergroups/permissions.py +9 -9
  199. reconcile/gql_definitions/slack_usergroups/users.py +5 -5
  200. reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
  201. reconcile/gql_definitions/status_board/status_board.py +6 -7
  202. reconcile/gql_definitions/statuspage/statuspages.py +9 -9
  203. reconcile/gql_definitions/templating/template_collection.py +5 -5
  204. reconcile/gql_definitions/templating/templates.py +5 -5
  205. reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +6 -6
  206. reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +11 -11
  207. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +11 -11
  208. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +20 -25
  209. reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +6 -6
  210. reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +12 -12
  211. reconcile/gql_definitions/terraform_init/aws_accounts.py +23 -9
  212. reconcile/gql_definitions/terraform_repo/terraform_repo.py +9 -9
  213. reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
  214. reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +450 -402
  215. reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +23 -17
  216. reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +9 -9
  217. reconcile/gql_definitions/vault_instances/vault_instances.py +61 -61
  218. reconcile/gql_definitions/vault_policies/vault_policies.py +11 -11
  219. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +8 -8
  220. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
  221. reconcile/integrations_manager.py +3 -3
  222. reconcile/jenkins_job_builder.py +1 -1
  223. reconcile/jenkins_worker_fleets.py +80 -11
  224. reconcile/jira_permissions_validator.py +237 -122
  225. reconcile/ldap_groups/integration.py +1 -1
  226. reconcile/ocm/types.py +35 -56
  227. reconcile/ocm_aws_infrastructure_access.py +1 -1
  228. reconcile/ocm_clusters.py +4 -4
  229. reconcile/ocm_labels/integration.py +3 -2
  230. reconcile/ocm_machine_pools.py +33 -27
  231. reconcile/openshift_base.py +122 -10
  232. reconcile/openshift_cluster_bots.py +5 -5
  233. reconcile/openshift_groups.py +5 -0
  234. reconcile/openshift_limitranges.py +1 -1
  235. reconcile/openshift_namespace_labels.py +1 -1
  236. reconcile/openshift_namespaces.py +97 -101
  237. reconcile/openshift_resources_base.py +10 -5
  238. reconcile/openshift_rhcs_certs.py +77 -40
  239. reconcile/openshift_rolebindings.py +230 -130
  240. reconcile/openshift_saas_deploy.py +6 -7
  241. reconcile/openshift_saas_deploy_change_tester.py +9 -7
  242. reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
  243. reconcile/openshift_serviceaccount_tokens.py +8 -7
  244. reconcile/openshift_tekton_resources.py +1 -1
  245. reconcile/openshift_upgrade_watcher.py +4 -4
  246. reconcile/openshift_users.py +5 -3
  247. reconcile/oum/labelset.py +5 -3
  248. reconcile/oum/models.py +1 -4
  249. reconcile/oum/providers.py +1 -1
  250. reconcile/prometheus_rules_tester/integration.py +4 -4
  251. reconcile/quay_mirror.py +1 -1
  252. reconcile/queries.py +131 -0
  253. reconcile/requests_sender.py +8 -3
  254. reconcile/resource_scraper.py +1 -5
  255. reconcile/rhidp/common.py +3 -5
  256. reconcile/rhidp/sso_client/base.py +19 -10
  257. reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
  258. reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
  259. reconcile/sendgrid_teammates.py +20 -9
  260. reconcile/skupper_network/integration.py +2 -2
  261. reconcile/slack_usergroups.py +35 -14
  262. reconcile/sql_query.py +1 -0
  263. reconcile/status.py +2 -2
  264. reconcile/status_board.py +6 -6
  265. reconcile/statuspage/atlassian.py +7 -7
  266. reconcile/statuspage/integrations/maintenances.py +4 -3
  267. reconcile/statuspage/page.py +4 -9
  268. reconcile/statuspage/status.py +5 -8
  269. reconcile/templates/rosa-classic-cluster-creation.sh.j2 +5 -1
  270. reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +4 -1
  271. reconcile/templating/lib/merge_request_manager.py +2 -2
  272. reconcile/templating/lib/rendering.py +3 -3
  273. reconcile/templating/renderer.py +12 -13
  274. reconcile/terraform_aws_route53.py +18 -8
  275. reconcile/terraform_cloudflare_dns.py +3 -3
  276. reconcile/terraform_cloudflare_resources.py +12 -13
  277. reconcile/terraform_cloudflare_users.py +3 -2
  278. reconcile/terraform_init/integration.py +187 -23
  279. reconcile/terraform_repo.py +16 -12
  280. reconcile/terraform_resources.py +18 -10
  281. reconcile/terraform_tgw_attachments.py +28 -20
  282. reconcile/terraform_users.py +27 -22
  283. reconcile/terraform_vpc_peerings.py +15 -3
  284. reconcile/terraform_vpc_resources/integration.py +23 -8
  285. reconcile/typed_queries/app_interface_roles.py +10 -0
  286. reconcile/typed_queries/aws_account_tags.py +41 -0
  287. reconcile/typed_queries/cost_report/app_names.py +1 -1
  288. reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
  289. reconcile/typed_queries/saas_files.py +13 -13
  290. reconcile/typed_queries/status_board.py +2 -2
  291. reconcile/unleash_feature_toggles/integration.py +4 -2
  292. reconcile/utils/acs/base.py +6 -3
  293. reconcile/utils/acs/policies.py +2 -2
  294. reconcile/utils/aggregated_list.py +4 -3
  295. reconcile/utils/aws_api.py +51 -20
  296. reconcile/utils/aws_api_typed/api.py +38 -9
  297. reconcile/utils/aws_api_typed/cloudformation.py +149 -0
  298. reconcile/utils/aws_api_typed/logs.py +73 -0
  299. reconcile/utils/aws_api_typed/organization.py +4 -2
  300. reconcile/utils/binary.py +7 -12
  301. reconcile/utils/datetime_util.py +67 -0
  302. reconcile/utils/deadmanssnitch_api.py +1 -1
  303. reconcile/utils/differ.py +2 -3
  304. reconcile/utils/early_exit_cache.py +11 -12
  305. reconcile/utils/expiration.py +7 -3
  306. reconcile/utils/external_resource_spec.py +24 -1
  307. reconcile/utils/filtering.py +1 -1
  308. reconcile/utils/gitlab_api.py +7 -5
  309. reconcile/utils/glitchtip/client.py +6 -2
  310. reconcile/utils/glitchtip/models.py +25 -28
  311. reconcile/utils/gpg.py +5 -3
  312. reconcile/utils/gql.py +4 -7
  313. reconcile/utils/helm.py +2 -1
  314. reconcile/utils/helpers.py +1 -1
  315. reconcile/utils/imap_client.py +1 -1
  316. reconcile/utils/instrumented_wrappers.py +1 -1
  317. reconcile/utils/internal_groups/client.py +2 -2
  318. reconcile/utils/internal_groups/models.py +8 -17
  319. reconcile/utils/jenkins_api.py +24 -1
  320. reconcile/utils/jinja2/utils.py +6 -8
  321. reconcile/utils/jira_client.py +82 -63
  322. reconcile/utils/jjb_client.py +78 -46
  323. reconcile/utils/jobcontroller/controller.py +2 -2
  324. reconcile/utils/jobcontroller/models.py +17 -1
  325. reconcile/utils/json.py +74 -0
  326. reconcile/utils/ldap_client.py +4 -3
  327. reconcile/utils/lean_terraform_client.py +3 -1
  328. reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
  329. reconcile/utils/membershipsources/models.py +16 -23
  330. reconcile/utils/membershipsources/resolver.py +4 -2
  331. reconcile/utils/merge_request_manager/merge_request_manager.py +4 -4
  332. reconcile/utils/merge_request_manager/parser.py +6 -6
  333. reconcile/utils/metrics.py +5 -5
  334. reconcile/utils/models.py +304 -82
  335. reconcile/utils/mr/__init__.py +3 -1
  336. reconcile/utils/mr/app_interface_reporter.py +6 -3
  337. reconcile/utils/mr/aws_access.py +1 -1
  338. reconcile/utils/mr/base.py +7 -13
  339. reconcile/utils/mr/clusters_updates.py +4 -2
  340. reconcile/utils/mr/notificator.py +3 -3
  341. reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py +4 -1
  342. reconcile/utils/mr/promote_qontract.py +28 -12
  343. reconcile/utils/mr/update_access_report_base.py +3 -4
  344. reconcile/utils/mr/user_maintenance.py +7 -6
  345. reconcile/utils/oc.py +445 -336
  346. reconcile/utils/oc_filters.py +3 -3
  347. reconcile/utils/ocm/addons.py +0 -1
  348. reconcile/utils/ocm/base.py +18 -21
  349. reconcile/utils/ocm/cluster_groups.py +1 -1
  350. reconcile/utils/ocm/identity_providers.py +2 -2
  351. reconcile/utils/ocm/labels.py +1 -1
  352. reconcile/utils/ocm/ocm.py +81 -71
  353. reconcile/utils/ocm/products.py +9 -3
  354. reconcile/utils/ocm/search_filters.py +3 -6
  355. reconcile/utils/ocm/service_log.py +4 -6
  356. reconcile/utils/ocm/sre_capability_labels.py +20 -13
  357. reconcile/utils/ocm_base_client.py +4 -4
  358. reconcile/utils/openshift_resource.py +83 -52
  359. reconcile/utils/openssl.py +2 -2
  360. reconcile/utils/output.py +3 -2
  361. reconcile/utils/pagerduty_api.py +10 -7
  362. reconcile/utils/promotion_state.py +6 -11
  363. reconcile/utils/raw_github_api.py +11 -8
  364. reconcile/utils/repo_owners.py +21 -29
  365. reconcile/utils/rhcsv2_certs.py +138 -35
  366. reconcile/utils/rosa/session.py +16 -0
  367. reconcile/utils/runtime/integration.py +2 -3
  368. reconcile/utils/runtime/meta.py +2 -1
  369. reconcile/utils/runtime/runner.py +2 -2
  370. reconcile/utils/saasherder/interfaces.py +13 -20
  371. reconcile/utils/saasherder/models.py +25 -21
  372. reconcile/utils/saasherder/saasherder.py +60 -32
  373. reconcile/utils/secret_reader.py +6 -6
  374. reconcile/utils/sharding.py +1 -1
  375. reconcile/utils/slack_api.py +26 -4
  376. reconcile/utils/sloth.py +224 -0
  377. reconcile/utils/sqs_gateway.py +16 -11
  378. reconcile/utils/state.py +2 -1
  379. reconcile/utils/structs.py +1 -1
  380. reconcile/utils/terraform_client.py +29 -26
  381. reconcile/utils/terrascript_aws_client.py +200 -116
  382. reconcile/utils/three_way_diff_strategy.py +1 -1
  383. reconcile/utils/unleash/server.py +2 -8
  384. reconcile/utils/vault.py +44 -41
  385. reconcile/utils/vcs.py +8 -8
  386. reconcile/vault_replication.py +119 -58
  387. tools/app_interface_reporter.py +4 -4
  388. tools/cli_commands/cost_report/cost_management_api.py +3 -3
  389. tools/cli_commands/cost_report/view.py +7 -6
  390. tools/cli_commands/erv2.py +1 -1
  391. tools/cli_commands/gpg_encrypt.py +4 -1
  392. tools/cli_commands/systems_and_tools.py +5 -1
  393. tools/qontract_cli.py +36 -21
  394. tools/template_validation.py +3 -1
  395. reconcile/gql_definitions/ocm_oidc_idp/__init__.py +0 -0
  396. reconcile/gql_definitions/ocm_subscription_labels/__init__.py +0 -0
  397. reconcile/jenkins/__init__.py +0 -0
  398. reconcile/jenkins/types.py +0 -77
  399. {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/WHEEL +0 -0
  400. {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/entry_points.txt +0 -0
@@ -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
@@ -342,11 +343,11 @@ def _populate_tgw_attachments_working_dirs(
342
343
  ts: Terrascript,
343
344
  desired_state: Iterable[DesiredStateItem],
344
345
  print_to_file: str | None,
345
- ) -> Mapping[str, str]:
346
+ ) -> dict[str, str]:
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:
@@ -1,9 +1,8 @@
1
1
  import sys
2
- from collections.abc import Mapping
2
+ from collections.abc import Iterable, Mapping
3
3
  from textwrap import indent
4
4
  from typing import (
5
5
  Any,
6
- cast,
7
6
  )
8
7
 
9
8
  from reconcile import (
@@ -12,6 +11,7 @@ from reconcile import (
12
11
  )
13
12
  from reconcile.change_owners.diff import IDENTIFIER_FIELD_NAME
14
13
  from reconcile.gql_definitions.common.pgp_reencryption_settings import query
14
+ from reconcile.typed_queries.external_resources import get_settings
15
15
  from reconcile.utils import (
16
16
  expiration,
17
17
  gql,
@@ -31,7 +31,6 @@ from reconcile.utils.terraform_client import TerraformClient as Terraform
31
31
  from reconcile.utils.terrascript_aws_client import TerrascriptClient as Terrascript
32
32
  from reconcile.utils.vault import (
33
33
  VaultClient,
34
- _VaultClient,
35
34
  )
36
35
 
37
36
  TF_POLICY = """
@@ -96,9 +95,9 @@ def get_tf_roles() -> list[Role]:
96
95
 
97
96
 
98
97
  def _filter_participating_aws_accounts(
99
- accounts: list,
100
- roles: list[dict[str, Any]],
101
- ) -> list:
98
+ accounts: Iterable[dict[str, Any]],
99
+ roles: Iterable[Mapping[str, Any]],
100
+ ) -> list[dict[str, Any]]:
102
101
  participating_aws_account_names: set[str] = set()
103
102
  for role in roles:
104
103
  participating_aws_account_names.update(
@@ -112,12 +111,12 @@ def _filter_participating_aws_accounts(
112
111
 
113
112
 
114
113
  def setup(
115
- print_to_file,
114
+ print_to_file: str | None,
116
115
  thread_pool_size: int,
117
116
  skip_reencrypt_accounts: list[str],
118
117
  appsre_pgp_key: str | None = None,
119
118
  account_name: str | None = None,
120
- ) -> tuple[list[dict[str, Any]], Mapping[str, str], bool, AWSApi]:
119
+ ) -> tuple[list[dict[str, Any]], dict[str, str], bool, AWSApi]:
121
120
  accounts = [
122
121
  a
123
122
  for a in queries.get_aws_accounts(terraform_state=True)
@@ -128,12 +127,18 @@ def setup(
128
127
  participating_aws_accounts = _filter_participating_aws_accounts(accounts, roles)
129
128
 
130
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
131
135
  ts = Terrascript(
132
136
  QONTRACT_INTEGRATION,
133
137
  QONTRACT_TF_PREFIX,
134
138
  thread_pool_size,
135
139
  participating_aws_accounts,
136
140
  settings=settings,
141
+ default_tags=default_tags,
137
142
  )
138
143
  err = ts.populate_users(
139
144
  roles,
@@ -147,10 +152,10 @@ def setup(
147
152
 
148
153
 
149
154
  def send_email_invites(
150
- new_users,
155
+ new_users: Iterable[tuple[str, str, str, str]],
151
156
  smtp_client: SmtpClient,
152
- skip_reencrypt_accounts: list[str],
153
- ):
157
+ skip_reencrypt_accounts: Iterable[str],
158
+ ) -> None:
154
159
  msg_template = """
155
160
  You have been invited to join the {} AWS account!
156
161
  Below you will find credentials for the first sign in.
@@ -188,11 +193,11 @@ Encrypted password: {}
188
193
 
189
194
 
190
195
  def write_user_to_vault(
191
- vault_client: _VaultClient,
196
+ vault_client: VaultClient,
192
197
  vault_path: str,
193
- new_users: list[tuple[str, str, str, str]],
194
- skip_reencrypt_accounts: list[str],
195
- ):
198
+ new_users: Iterable[tuple[str, str, str, str]],
199
+ skip_reencrypt_accounts: Iterable[str],
200
+ ) -> None:
196
201
  for account, console_url, user_name, enc_password in new_users:
197
202
  if account in skip_reencrypt_accounts:
198
203
  continue
@@ -209,13 +214,13 @@ def write_user_to_vault(
209
214
  vault_client.write(desired_secret, decode_base64=False)
210
215
 
211
216
 
212
- def cleanup_and_exit(tf=None, status=False):
217
+ def cleanup_and_exit(tf: Terraform | None = None, status: bool = False) -> None:
213
218
  if tf is not None:
214
219
  tf.cleanup()
215
220
  sys.exit(status)
216
221
 
217
222
 
218
- def get_reencrypt_settings():
223
+ def get_reencrypt_settings() -> tuple[list[str], str | None, Any]:
219
224
  all_reencrypt_settings = query(
220
225
  query_func=gql.get_api().query
221
226
  ).pgp_reencryption_settings
@@ -244,7 +249,7 @@ def run(
244
249
  thread_pool_size: int = DEFAULT_THREAD_POOL_SIZE,
245
250
  send_mails: bool = True,
246
251
  account_name: str | None = None,
247
- ):
252
+ ) -> None:
248
253
  skip_accounts, appsre_pgp_key, reencrypt_settings = get_reencrypt_settings()
249
254
 
250
255
  # setup errors should skip resources that will lead
@@ -298,7 +303,7 @@ def run(
298
303
  new_users = tf.get_new_users()
299
304
 
300
305
  if reencrypt_settings:
301
- vc = cast("_VaultClient", VaultClient())
306
+ vc = VaultClient.get_instance()
302
307
  write_user_to_vault(
303
308
  vc, reencrypt_settings.reencrypt_vault_path, new_users, skip_accounts
304
309
  )
@@ -320,7 +325,7 @@ def run(
320
325
  cleanup_and_exit(tf, setup_err)
321
326
 
322
327
 
323
- def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
328
+ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
324
329
  """
325
330
  Finding diffs in deeply nested structures is time/resource consuming.
326
331
  Having a unique known property to identify objects makes it easier to match
@@ -331,11 +336,11 @@ def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
331
336
  for the DeepDiff library used in qontract-reconcile.
332
337
  """
333
338
 
334
- def add_account_identity(acc):
339
+ def add_account_identity(acc: dict[str, Any]) -> dict[str, Any]:
335
340
  acc[IDENTIFIER_FIELD_NAME] = acc["path"]
336
341
  return acc
337
342
 
338
- def add_role_identity(role):
343
+ def add_role_identity(role: dict[str, Any]) -> dict[str, Any]:
339
344
  role[IDENTIFIER_FIELD_NAME] = role["name"]
340
345
  return role
341
346
 
@@ -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,
@@ -73,6 +74,7 @@ def _build_infrastructure_assume_role(
73
74
  ocm: OCM | None,
74
75
  provided_assume_role: str | None,
75
76
  ) -> dict[str, Any] | None:
77
+ assume_role: str | None = None
76
78
  if provided_assume_role:
77
79
  assume_role = provided_assume_role
78
80
  elif cluster["spec"].get("account"):
@@ -653,8 +655,18 @@ def run(
653
655
  ])
654
656
 
655
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
656
663
  with terrascript.TerrascriptClient(
657
- 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,
658
670
  ) as ts:
659
671
  rosa_cluster_accounts = [
660
672
  account_by_name[c["spec"]["account"]["name"]]
@@ -663,8 +675,8 @@ def run(
663
675
  ]
664
676
  ts.populate_configs(rosa_cluster_accounts)
665
677
 
666
- for infra_account_name, items in participating_accounts.items():
667
- 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)
668
680
  ts.populate_vpc_peerings(desired_state)
669
681
  working_dirs = ts.dump(print_to_file=print_to_file)
670
682
  terraform_configurations = ts.terraform_configurations()
@@ -20,9 +20,11 @@ from reconcile.typed_queries.app_interface_vault_settings import (
20
20
  get_app_interface_vault_settings,
21
21
  )
22
22
  from reconcile.typed_queries.aws_vpc_requests import get_aws_vpc_requests
23
+ from reconcile.typed_queries.external_resources import get_settings
23
24
  from reconcile.typed_queries.github_orgs import get_github_orgs
24
25
  from reconcile.typed_queries.gitlab_instances import get_gitlab_instances
25
26
  from reconcile.utils import gql
27
+ from reconcile.utils.disabled_integrations import integration_is_enabled
26
28
  from reconcile.utils.runtime.integration import (
27
29
  DesiredStateShardConfig,
28
30
  PydanticRunParams,
@@ -61,12 +63,14 @@ class TerraformVpcResources(QontractReconcileIntegration[TerraformVpcResourcesPa
61
63
  ) -> list[AWSAccountV1]:
62
64
  """Return a list of accounts extracted from the provided VPCRequests.
63
65
  If account_name is given returns the account object with that name."""
64
- accounts = [vpc.account for vpc in data]
65
-
66
- if account_name:
67
- accounts = [account for account in accounts if account.name == account_name]
68
-
69
- return accounts
66
+ return [
67
+ vpc.account
68
+ for vpc in data
69
+ if (
70
+ integration_is_enabled(self.name, vpc.account)
71
+ and (not account_name or vpc.account.name == account_name)
72
+ )
73
+ ]
70
74
 
71
75
  def _handle_outputs(
72
76
  self, requests: Iterable[VPCRequest], outputs: Mapping[str, Any]
@@ -93,6 +97,7 @@ class TerraformVpcResources(QontractReconcileIntegration[TerraformVpcResourcesPa
93
97
  public_subnets = outputs_per_account.get(
94
98
  f"{request.identifier}-public_subnets", {}
95
99
  ).get("value", [])
100
+ availability_zones: list[str] = []
96
101
 
97
102
  if request.subnets:
98
103
  private_subnet_tags = VPC_REQUEST_DEFAULT_PRIVATE_SUBNET_TAGS | (
@@ -101,6 +106,7 @@ class TerraformVpcResources(QontractReconcileIntegration[TerraformVpcResourcesPa
101
106
  public_subnet_tags = VPC_REQUEST_DEFAULT_PUBLIC_SUBNET_TAGS | (
102
107
  request.subnets.public_subnet_tags or {}
103
108
  )
109
+ availability_zones = request.subnets.availability_zones or []
104
110
  else:
105
111
  private_subnet_tags = VPC_REQUEST_DEFAULT_PRIVATE_SUBNET_TAGS
106
112
  public_subnet_tags = VPC_REQUEST_DEFAULT_PUBLIC_SUBNET_TAGS
@@ -116,6 +122,7 @@ class TerraformVpcResources(QontractReconcileIntegration[TerraformVpcResourcesPa
116
122
  "public": public_subnets,
117
123
  "private_subnet_tags": private_subnet_tags,
118
124
  "public_subnet_tags": public_subnet_tags,
125
+ "availability_zones": availability_zones,
119
126
  },
120
127
  "account_name": request.account.name,
121
128
  "region": request.region,
@@ -151,20 +158,28 @@ class TerraformVpcResources(QontractReconcileIntegration[TerraformVpcResourcesPa
151
158
  if data:
152
159
  accounts = self._filter_accounts(data, account_name)
153
160
  if account_name and not accounts:
154
- msg = f"The account {account_name} doesn't have any managed vpc. Verify your input"
161
+ msg = f"The account {account_name} doesn't have any managed vpcs or the {QONTRACT_INTEGRATION} integration is disabled for this account. Verify your input"
155
162
  logging.debug(msg)
156
163
  sys.exit(ExitCodes.SUCCESS)
157
164
  else:
158
165
  logging.debug("No VPC requests found, nothing to do.")
159
166
  sys.exit(ExitCodes.SUCCESS)
160
167
 
161
- accounts_untyped: list[dict] = [acc.dict(by_alias=True) for acc in accounts]
168
+ accounts_untyped: list[dict] = [
169
+ acc.model_dump(by_alias=True) for acc in accounts
170
+ ]
171
+ try:
172
+ default_tags = get_settings().default_tags
173
+ except ValueError:
174
+ # no external resources settings found
175
+ default_tags = None
162
176
  with TerrascriptClient(
163
177
  integration=QONTRACT_INTEGRATION,
164
178
  integration_prefix=QONTRACT_TF_PREFIX,
165
179
  thread_pool_size=thread_pool_size,
166
180
  accounts=accounts_untyped,
167
181
  secret_reader=secret_reader,
182
+ default_tags=default_tags,
168
183
  ) as ts_client:
169
184
  ts_client.populate_vpc_requests(data, AWS_PROVIDER_VERSION)
170
185
 
@@ -0,0 +1,10 @@
1
+ from reconcile.gql_definitions.common.app_interface_roles import (
2
+ RoleV1,
3
+ query,
4
+ )
5
+ from reconcile.utils import gql
6
+
7
+
8
+ def get_app_interface_roles() -> list[RoleV1]:
9
+ data = query(gql.get_api().query)
10
+ return list(data.roles or [])
@@ -0,0 +1,41 @@
1
+ import json
2
+ from collections.abc import Mapping
3
+
4
+ from reconcile.gql_definitions.fragments.aws_organization import (
5
+ AWSOrganization,
6
+ )
7
+
8
+
9
+ def get_aws_account_tags(
10
+ organization: AWSOrganization | Mapping | None,
11
+ ) -> dict[str, str]:
12
+ """
13
+ Get AWS account tags by merging payer account tags
14
+
15
+ Args:
16
+ organization: AWSOrganization | Mapping | None - The organization object from which to extract tags.
17
+
18
+ Returns:
19
+ dict[str, str]: A dictionary containing the merged tags from the payer account and the account itself.
20
+ """
21
+ if organization is None:
22
+ return {}
23
+
24
+ match organization:
25
+ case AWSOrganization():
26
+ payer_account_tags = (
27
+ organization.payer_account.organization_account_tags or {}
28
+ )
29
+ account_tags = organization.tags or {}
30
+ case Mapping():
31
+ payer_account_tags = organization.get("payerAccount", {}).get(
32
+ "organizationAccountTags", {}
33
+ )
34
+ if isinstance(payer_account_tags, str):
35
+ payer_account_tags = json.loads(payer_account_tags)
36
+
37
+ account_tags = organization.get("tags", {})
38
+ if isinstance(account_tags, str):
39
+ account_tags = json.loads(account_tags)
40
+
41
+ return payer_account_tags | account_tags
@@ -6,7 +6,7 @@ from reconcile.utils.gql import GqlApi
6
6
 
7
7
  class App(BaseModel):
8
8
  name: str
9
- parent_app_name: str | None
9
+ parent_app_name: str | None = None
10
10
 
11
11
 
12
12
  def get_app_names(
@@ -13,7 +13,7 @@ class CostNamespace(BaseModel, frozen=True):
13
13
  labels: CostNamespaceLabels
14
14
  app_name: str
15
15
  cluster_name: str
16
- cluster_external_id: str | None
16
+ cluster_external_id: str | None = None
17
17
 
18
18
 
19
19
  def get_cost_namespaces(
@@ -32,7 +32,7 @@ def get_cost_namespaces(
32
32
  return [
33
33
  CostNamespace(
34
34
  name=namespace.name,
35
- labels=CostNamespaceLabels.parse_obj(namespace.labels or {}),
35
+ labels=CostNamespaceLabels.model_validate(namespace.labels or {}),
36
36
  app_name=namespace.app.name,
37
37
  cluster_name=namespace.cluster.name,
38
38
  cluster_external_id=namespace.cluster.spec.external_id
@@ -1,5 +1,4 @@
1
1
  import hashlib
2
- import json
3
2
  from collections.abc import Callable
4
3
  from threading import Lock
5
4
  from typing import Any
@@ -7,7 +6,6 @@ from typing import Any
7
6
  from jsonpath_ng.exceptions import JsonPathParserError
8
7
  from pydantic import (
9
8
  BaseModel,
10
- Extra,
11
9
  Field,
12
10
  Json,
13
11
  )
@@ -48,10 +46,16 @@ from reconcile.utils.exceptions import (
48
46
  AppInterfaceSettingsError,
49
47
  ParameterError,
50
48
  )
49
+ from reconcile.utils.json import json_dumps
51
50
  from reconcile.utils.jsonpath import parse_jsonpath
52
51
 
53
52
 
54
- class SaasResourceTemplateTarget(ConfiguredBaseModel):
53
+ class SaasResourceTemplateTarget(
54
+ ConfiguredBaseModel,
55
+ validate_by_alias=True,
56
+ # ignore `namespaceSelector` and 'provider' fields from the GQL schema
57
+ extra="ignore",
58
+ ):
55
59
  path: str | None = Field(..., alias="path")
56
60
  name: str | None = Field(..., alias="name")
57
61
  # the namespace must be required to fulfill the saas file schema (utils.saasherder.interface.SaasFile)
@@ -79,12 +83,8 @@ class SaasResourceTemplateTarget(ConfiguredBaseModel):
79
83
  digest_size=20,
80
84
  ).hexdigest()
81
85
 
82
- class Config:
83
- # ignore `namespaceSelector` and 'provider' fields from the GQL schema
84
- extra = Extra.ignore
85
-
86
86
 
87
- class SaasResourceTemplate(ConfiguredBaseModel):
87
+ class SaasResourceTemplate(ConfiguredBaseModel, validate_by_alias=True):
88
88
  name: str = Field(..., alias="name")
89
89
  url: str = Field(..., alias="url")
90
90
  path: str = Field(..., alias="path")
@@ -97,7 +97,7 @@ class SaasResourceTemplate(ConfiguredBaseModel):
97
97
  targets: list[SaasResourceTemplateTarget] = Field(..., alias="targets")
98
98
 
99
99
 
100
- class SaasFile(ConfiguredBaseModel):
100
+ class SaasFile(ConfiguredBaseModel, validate_by_alias=True):
101
101
  path: str = Field(..., alias="path")
102
102
  name: str = Field(..., alias="name")
103
103
  labels: Json | None = Field(..., alias="labels")
@@ -221,7 +221,7 @@ class SaasFileList:
221
221
  with self._namespaces_as_dict_lock:
222
222
  self._namespaces_as_dict_cache = {
223
223
  "namespace": [
224
- ns.dict(by_alias=True, exclude_none=True)
224
+ ns.model_dump(by_alias=True, exclude_none=True)
225
225
  for ns in self.namespaces
226
226
  ]
227
227
  }
@@ -283,7 +283,7 @@ class SaasFileList:
283
283
  if app_name and saas_file.app.name != app_name:
284
284
  continue
285
285
 
286
- sf = saas_file.copy(deep=True)
286
+ sf = saas_file.model_copy(deep=True)
287
287
  if env_name:
288
288
  for rt in sf.resource_templates[:]:
289
289
  for target in rt.targets[:]:
@@ -302,7 +302,7 @@ def convert_parameters_to_json_string(root: dict[str, Any]) -> dict[str, Any]:
302
302
  """Find all parameter occurrences and convert them to a json string."""
303
303
  for key, value in root.items():
304
304
  if key in {"parameters", "labels"}:
305
- root[key] = json.dumps(value) if value is not None else None
305
+ root[key] = json_dumps(value) if value is not None else None
306
306
  elif isinstance(value, dict):
307
307
  root[key] = convert_parameters_to_json_string(value)
308
308
  elif isinstance(value, list):
@@ -314,7 +314,7 @@ def convert_parameters_to_json_string(root: dict[str, Any]) -> dict[str, Any]:
314
314
 
315
315
 
316
316
  def export_model(model: BaseModel) -> dict[str, Any]:
317
- return convert_parameters_to_json_string(model.dict(by_alias=True))
317
+ return convert_parameters_to_json_string(model.model_dump(by_alias=True))
318
318
 
319
319
 
320
320
  def get_saas_files(
@@ -32,7 +32,7 @@ def get_selected_app_names(
32
32
  prefix = f"{namespace.app.parent_app.name}-"
33
33
  name = f"{prefix}{namespace.app.name}"
34
34
  selected_app_names.add(name)
35
- app = namespace.app.dict(by_alias=True)
35
+ app = namespace.app.model_dump(by_alias=True)
36
36
  app["name"] = name
37
37
  apps["apps"].append(app)
38
38
 
@@ -40,7 +40,7 @@ def get_selected_app_names(
40
40
  name = f"{namespace.app.name}-{child.name}"
41
41
  if name not in selected_app_names:
42
42
  selected_app_names.add(f"{namespace.app.name}-{child.name}")
43
- child_dict = child.dict(by_alias=True)
43
+ child_dict = child.model_dump(by_alias=True)
44
44
  child_dict["name"] = name
45
45
  apps["apps"].append(child_dict)
46
46
 
@@ -31,7 +31,7 @@ QONTRACT_INTEGRATION_VERSION = make_semver(1, 0, 0)
31
31
 
32
32
 
33
33
  class UnleashTogglesIntegrationParams(PydanticRunParams):
34
- instance: str | None
34
+ instance: str | None = None
35
35
 
36
36
 
37
37
  def feature_toggle_equal(c: FeatureToggle, d: FeatureToggleUnleashV1) -> bool:
@@ -68,7 +68,9 @@ class UnleashTogglesIntegration(
68
68
  if not query_func:
69
69
  query_func = gql.get_api().query
70
70
  return {
71
- "toggles": [ft.dict() for ft in self.get_unleash_instances(query_func)],
71
+ "toggles": [
72
+ ft.model_dump() for ft in self.get_unleash_instances(query_func)
73
+ ],
72
74
  }
73
75
 
74
76
  def get_unleash_instances(
@@ -6,7 +6,7 @@ from typing import (
6
6
  )
7
7
 
8
8
  import requests
9
- from pydantic import BaseModel
9
+ from pydantic import BaseModel, ConfigDict
10
10
 
11
11
  from reconcile.gql_definitions.acs.acs_instances import AcsInstanceV1
12
12
  from reconcile.gql_definitions.acs.acs_instances import query as acs_instances_query
@@ -19,8 +19,11 @@ class AcsBaseApi(BaseModel):
19
19
  timeout: int = 30
20
20
  session: requests.Session = requests.Session()
21
21
 
22
- class Config:
23
- arbitrary_types_allowed = True
22
+ model_config = ConfigDict(
23
+ validate_by_name=True,
24
+ validate_by_alias=True,
25
+ arbitrary_types_allowed=True,
26
+ )
24
27
 
25
28
  def __enter__(self) -> Self:
26
29
  return self