qontract-reconcile 0.10.0__py3-none-any.whl → 0.10.1.dev1203__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 (844) hide show
  1. qontract_reconcile-0.10.1.dev1203.dist-info/METADATA +500 -0
  2. qontract_reconcile-0.10.1.dev1203.dist-info/RECORD +771 -0
  3. {qontract_reconcile-0.10.0.dist-info → qontract_reconcile-0.10.1.dev1203.dist-info}/WHEEL +1 -2
  4. {qontract_reconcile-0.10.0.dist-info → qontract_reconcile-0.10.1.dev1203.dist-info}/entry_points.txt +4 -2
  5. reconcile/acs_notifiers.py +126 -0
  6. reconcile/acs_policies.py +243 -0
  7. reconcile/acs_rbac.py +596 -0
  8. reconcile/aus/advanced_upgrade_service.py +621 -8
  9. reconcile/aus/aus_label_source.py +115 -0
  10. reconcile/aus/base.py +1053 -353
  11. reconcile/{utils → aus}/cluster_version_data.py +27 -12
  12. reconcile/aus/healthchecks.py +77 -0
  13. reconcile/aus/metrics.py +158 -0
  14. reconcile/aus/models.py +245 -5
  15. reconcile/aus/node_pool_spec.py +35 -0
  16. reconcile/aus/ocm_addons_upgrade_scheduler_org.py +225 -110
  17. reconcile/aus/ocm_upgrade_scheduler.py +76 -71
  18. reconcile/aus/ocm_upgrade_scheduler_org.py +81 -23
  19. reconcile/aus/version_gate_approver.py +204 -0
  20. reconcile/aus/version_gates/__init__.py +12 -0
  21. reconcile/aus/version_gates/handler.py +33 -0
  22. reconcile/aus/version_gates/ingress_gate_handler.py +32 -0
  23. reconcile/aus/version_gates/ocp_gate_handler.py +26 -0
  24. reconcile/aus/version_gates/sts_version_gate_handler.py +100 -0
  25. reconcile/aws_account_manager/README.md +5 -0
  26. reconcile/aws_account_manager/integration.py +373 -0
  27. reconcile/aws_account_manager/merge_request_manager.py +114 -0
  28. reconcile/aws_account_manager/metrics.py +39 -0
  29. reconcile/aws_account_manager/reconciler.py +403 -0
  30. reconcile/aws_account_manager/utils.py +41 -0
  31. reconcile/aws_ami_cleanup/integration.py +273 -0
  32. reconcile/aws_ami_share.py +18 -14
  33. reconcile/aws_cloudwatch_log_retention/integration.py +253 -0
  34. reconcile/aws_iam_keys.py +1 -1
  35. reconcile/aws_iam_password_reset.py +56 -20
  36. reconcile/aws_saml_idp/integration.py +204 -0
  37. reconcile/aws_saml_roles/integration.py +322 -0
  38. reconcile/aws_support_cases_sos.py +2 -2
  39. reconcile/aws_version_sync/integration.py +430 -0
  40. reconcile/aws_version_sync/merge_request_manager/merge_request.py +156 -0
  41. reconcile/aws_version_sync/merge_request_manager/merge_request_manager.py +160 -0
  42. reconcile/aws_version_sync/utils.py +64 -0
  43. reconcile/blackbox_exporter_endpoint_monitoring.py +2 -5
  44. reconcile/change_owners/README.md +34 -0
  45. reconcile/change_owners/approver.py +7 -9
  46. reconcile/change_owners/bundle.py +134 -9
  47. reconcile/change_owners/change_log_tracking.py +236 -0
  48. reconcile/change_owners/change_owners.py +204 -194
  49. reconcile/change_owners/change_types.py +183 -265
  50. reconcile/change_owners/changes.py +488 -0
  51. reconcile/change_owners/decision.py +120 -41
  52. reconcile/change_owners/diff.py +63 -92
  53. reconcile/change_owners/implicit_ownership.py +19 -16
  54. reconcile/change_owners/self_service_roles.py +158 -35
  55. reconcile/change_owners/tester.py +20 -18
  56. reconcile/checkpoint.py +4 -6
  57. reconcile/cli.py +1523 -242
  58. reconcile/closedbox_endpoint_monitoring_base.py +10 -17
  59. reconcile/cluster_auth_rhidp/integration.py +257 -0
  60. reconcile/cluster_deployment_mapper.py +2 -5
  61. reconcile/cna/assets/asset.py +4 -7
  62. reconcile/cna/assets/null.py +2 -5
  63. reconcile/cna/integration.py +2 -3
  64. reconcile/cna/state.py +6 -9
  65. reconcile/dashdotdb_base.py +31 -10
  66. reconcile/dashdotdb_cso.py +3 -6
  67. reconcile/dashdotdb_dora.py +530 -0
  68. reconcile/dashdotdb_dvo.py +10 -13
  69. reconcile/dashdotdb_slo.py +75 -19
  70. reconcile/database_access_manager.py +753 -0
  71. reconcile/deadmanssnitch.py +207 -0
  72. reconcile/dynatrace_token_provider/dependencies.py +69 -0
  73. reconcile/dynatrace_token_provider/integration.py +656 -0
  74. reconcile/dynatrace_token_provider/metrics.py +62 -0
  75. reconcile/dynatrace_token_provider/model.py +14 -0
  76. reconcile/dynatrace_token_provider/ocm.py +140 -0
  77. reconcile/dynatrace_token_provider/validate.py +48 -0
  78. reconcile/endpoints_discovery/integration.py +348 -0
  79. reconcile/endpoints_discovery/merge_request.py +96 -0
  80. reconcile/endpoints_discovery/merge_request_manager.py +178 -0
  81. reconcile/external_resources/aws.py +204 -0
  82. reconcile/external_resources/factories.py +163 -0
  83. reconcile/external_resources/integration.py +194 -0
  84. reconcile/external_resources/integration_secrets_sync.py +47 -0
  85. reconcile/external_resources/manager.py +405 -0
  86. reconcile/external_resources/meta.py +17 -0
  87. reconcile/external_resources/metrics.py +95 -0
  88. reconcile/external_resources/model.py +350 -0
  89. reconcile/external_resources/reconciler.py +265 -0
  90. reconcile/external_resources/secrets_sync.py +465 -0
  91. reconcile/external_resources/state.py +258 -0
  92. reconcile/gabi_authorized_users.py +19 -11
  93. reconcile/gcr_mirror.py +43 -34
  94. reconcile/github_org.py +4 -6
  95. reconcile/github_owners.py +1 -1
  96. reconcile/github_repo_invites.py +2 -5
  97. reconcile/gitlab_fork_compliance.py +14 -13
  98. reconcile/gitlab_housekeeping.py +185 -91
  99. reconcile/gitlab_labeler.py +15 -14
  100. reconcile/gitlab_members.py +126 -120
  101. reconcile/gitlab_owners.py +53 -66
  102. reconcile/gitlab_permissions.py +167 -6
  103. reconcile/glitchtip/README.md +150 -0
  104. reconcile/glitchtip/integration.py +99 -51
  105. reconcile/glitchtip/reconciler.py +99 -70
  106. reconcile/glitchtip_project_alerts/__init__.py +0 -0
  107. reconcile/glitchtip_project_alerts/integration.py +333 -0
  108. reconcile/glitchtip_project_dsn/integration.py +43 -43
  109. reconcile/gql_definitions/acs/__init__.py +0 -0
  110. reconcile/gql_definitions/acs/acs_instances.py +83 -0
  111. reconcile/gql_definitions/acs/acs_policies.py +239 -0
  112. reconcile/gql_definitions/acs/acs_rbac.py +111 -0
  113. reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +46 -8
  114. reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +38 -8
  115. reconcile/gql_definitions/app_interface_metrics_exporter/__init__.py +0 -0
  116. reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +61 -0
  117. reconcile/gql_definitions/aws_account_manager/__init__.py +0 -0
  118. reconcile/gql_definitions/aws_account_manager/aws_accounts.py +177 -0
  119. reconcile/gql_definitions/aws_ami_cleanup/__init__.py +0 -0
  120. reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +161 -0
  121. reconcile/gql_definitions/aws_saml_idp/__init__.py +0 -0
  122. reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +117 -0
  123. reconcile/gql_definitions/aws_saml_roles/__init__.py +0 -0
  124. reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +117 -0
  125. reconcile/gql_definitions/aws_saml_roles/roles.py +97 -0
  126. reconcile/gql_definitions/aws_version_sync/__init__.py +0 -0
  127. reconcile/gql_definitions/aws_version_sync/clusters.py +83 -0
  128. reconcile/gql_definitions/aws_version_sync/namespaces.py +143 -0
  129. reconcile/gql_definitions/change_owners/queries/change_types.py +16 -29
  130. reconcile/gql_definitions/change_owners/queries/self_service_roles.py +45 -11
  131. reconcile/gql_definitions/cluster_auth_rhidp/__init__.py +0 -0
  132. reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +128 -0
  133. reconcile/gql_definitions/cna/queries/cna_provisioners.py +6 -8
  134. reconcile/gql_definitions/cna/queries/cna_resources.py +3 -5
  135. reconcile/gql_definitions/common/alerting_services_settings.py +2 -2
  136. reconcile/gql_definitions/common/app_code_component_repos.py +9 -5
  137. reconcile/gql_definitions/{glitchtip/glitchtip_settings.py → common/app_interface_custom_messages.py} +14 -16
  138. reconcile/gql_definitions/common/app_interface_dms_settings.py +86 -0
  139. reconcile/gql_definitions/common/app_interface_repo_settings.py +2 -2
  140. reconcile/gql_definitions/common/app_interface_state_settings.py +3 -5
  141. reconcile/gql_definitions/common/app_interface_vault_settings.py +3 -5
  142. reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +120 -0
  143. reconcile/gql_definitions/common/apps.py +72 -0
  144. reconcile/gql_definitions/common/aws_vpc_requests.py +109 -0
  145. reconcile/gql_definitions/common/aws_vpcs.py +84 -0
  146. reconcile/gql_definitions/common/clusters.py +120 -254
  147. reconcile/gql_definitions/common/clusters_minimal.py +11 -35
  148. reconcile/gql_definitions/common/clusters_with_dms.py +72 -0
  149. reconcile/gql_definitions/common/clusters_with_peering.py +70 -98
  150. reconcile/gql_definitions/common/github_orgs.py +2 -2
  151. reconcile/gql_definitions/common/jira_settings.py +68 -0
  152. reconcile/gql_definitions/common/jiralert_settings.py +68 -0
  153. reconcile/gql_definitions/common/namespaces.py +74 -32
  154. reconcile/gql_definitions/common/namespaces_minimal.py +4 -10
  155. reconcile/gql_definitions/common/ocm_env_telemeter.py +95 -0
  156. reconcile/gql_definitions/common/ocm_environments.py +4 -2
  157. reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
  158. reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -11
  159. reconcile/gql_definitions/common/pipeline_providers.py +45 -90
  160. reconcile/gql_definitions/common/quay_instances.py +64 -0
  161. reconcile/gql_definitions/common/quay_orgs.py +68 -0
  162. reconcile/gql_definitions/common/reserved_networks.py +94 -0
  163. reconcile/gql_definitions/common/saas_files.py +133 -95
  164. reconcile/gql_definitions/common/saas_target_namespaces.py +41 -26
  165. reconcile/gql_definitions/common/saasherder_settings.py +2 -2
  166. reconcile/gql_definitions/common/slack_workspaces.py +62 -0
  167. reconcile/gql_definitions/common/smtp_client_settings.py +2 -2
  168. reconcile/gql_definitions/common/state_aws_account.py +77 -0
  169. reconcile/gql_definitions/common/users.py +3 -2
  170. reconcile/gql_definitions/cost_report/__init__.py +0 -0
  171. reconcile/gql_definitions/cost_report/app_names.py +68 -0
  172. reconcile/gql_definitions/cost_report/cost_namespaces.py +86 -0
  173. reconcile/gql_definitions/cost_report/settings.py +77 -0
  174. reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +42 -12
  175. reconcile/gql_definitions/dynatrace_token_provider/__init__.py +0 -0
  176. reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +79 -0
  177. reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +84 -0
  178. reconcile/gql_definitions/endpoints_discovery/__init__.py +0 -0
  179. reconcile/gql_definitions/endpoints_discovery/namespaces.py +127 -0
  180. reconcile/gql_definitions/external_resources/__init__.py +0 -0
  181. reconcile/gql_definitions/external_resources/aws_accounts.py +73 -0
  182. reconcile/gql_definitions/external_resources/external_resources_modules.py +78 -0
  183. reconcile/gql_definitions/external_resources/external_resources_namespaces.py +1111 -0
  184. reconcile/gql_definitions/external_resources/external_resources_settings.py +98 -0
  185. reconcile/gql_definitions/fragments/aus_organization.py +34 -39
  186. reconcile/gql_definitions/fragments/aws_account_common.py +62 -0
  187. reconcile/gql_definitions/fragments/aws_account_managed.py +57 -0
  188. reconcile/gql_definitions/fragments/aws_account_sso.py +35 -0
  189. reconcile/gql_definitions/fragments/aws_infra_management_account.py +2 -2
  190. reconcile/gql_definitions/fragments/aws_vpc.py +47 -0
  191. reconcile/gql_definitions/fragments/aws_vpc_request.py +65 -0
  192. reconcile/gql_definitions/fragments/aws_vpc_request_subnet.py +29 -0
  193. reconcile/gql_definitions/fragments/deplopy_resources.py +7 -7
  194. reconcile/gql_definitions/fragments/disable.py +28 -0
  195. reconcile/gql_definitions/fragments/jumphost_common_fields.py +2 -2
  196. reconcile/gql_definitions/fragments/membership_source.py +47 -0
  197. reconcile/gql_definitions/fragments/minimal_ocm_organization.py +29 -0
  198. reconcile/gql_definitions/fragments/oc_connection_cluster.py +4 -9
  199. reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
  200. reconcile/gql_definitions/fragments/pipeline_provider_retention.py +30 -0
  201. reconcile/gql_definitions/fragments/prometheus_instance.py +48 -0
  202. reconcile/gql_definitions/fragments/resource_limits_requirements.py +29 -0
  203. reconcile/gql_definitions/fragments/{resource_requirements.py → resource_requests_requirements.py} +3 -3
  204. reconcile/gql_definitions/fragments/resource_values.py +2 -2
  205. reconcile/gql_definitions/fragments/saas_target_namespace.py +55 -12
  206. reconcile/gql_definitions/fragments/serviceaccount_token.py +38 -0
  207. reconcile/gql_definitions/fragments/terraform_state.py +36 -0
  208. reconcile/gql_definitions/fragments/upgrade_policy.py +5 -3
  209. reconcile/gql_definitions/fragments/user.py +3 -2
  210. reconcile/gql_definitions/fragments/vault_secret.py +2 -2
  211. reconcile/gql_definitions/gitlab_members/gitlab_instances.py +6 -2
  212. reconcile/gql_definitions/gitlab_members/permissions.py +3 -5
  213. reconcile/gql_definitions/glitchtip/glitchtip_instance.py +16 -2
  214. reconcile/gql_definitions/glitchtip/glitchtip_project.py +22 -23
  215. reconcile/gql_definitions/glitchtip_project_alerts/__init__.py +0 -0
  216. reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +173 -0
  217. reconcile/gql_definitions/integrations/integrations.py +62 -45
  218. reconcile/gql_definitions/introspection.json +51176 -0
  219. reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +13 -5
  220. reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +79 -0
  221. reconcile/gql_definitions/jira/__init__.py +0 -0
  222. reconcile/gql_definitions/jira/jira_servers.py +80 -0
  223. reconcile/gql_definitions/jira_permissions_validator/__init__.py +0 -0
  224. reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +131 -0
  225. reconcile/gql_definitions/jumphosts/jumphosts.py +3 -5
  226. reconcile/gql_definitions/ldap_groups/__init__.py +0 -0
  227. reconcile/gql_definitions/ldap_groups/roles.py +111 -0
  228. reconcile/gql_definitions/ldap_groups/settings.py +79 -0
  229. reconcile/gql_definitions/maintenance/__init__.py +0 -0
  230. reconcile/gql_definitions/maintenance/maintenances.py +101 -0
  231. reconcile/gql_definitions/membershipsources/__init__.py +0 -0
  232. reconcile/gql_definitions/membershipsources/roles.py +112 -0
  233. reconcile/gql_definitions/ocm_labels/__init__.py +0 -0
  234. reconcile/gql_definitions/ocm_labels/clusters.py +112 -0
  235. reconcile/gql_definitions/ocm_labels/organizations.py +78 -0
  236. reconcile/gql_definitions/ocm_subscription_labels/__init__.py +0 -0
  237. reconcile/gql_definitions/openshift_cluster_bots/__init__.py +0 -0
  238. reconcile/gql_definitions/openshift_cluster_bots/clusters.py +126 -0
  239. reconcile/gql_definitions/openshift_groups/managed_groups.py +2 -2
  240. reconcile/gql_definitions/openshift_groups/managed_roles.py +3 -2
  241. reconcile/gql_definitions/openshift_serviceaccount_tokens/__init__.py +0 -0
  242. reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +132 -0
  243. reconcile/gql_definitions/quay_membership/quay_membership.py +3 -5
  244. reconcile/gql_definitions/rhidp/__init__.py +0 -0
  245. reconcile/gql_definitions/rhidp/organizations.py +96 -0
  246. reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +2 -2
  247. reconcile/gql_definitions/service_dependencies/service_dependencies.py +9 -31
  248. reconcile/gql_definitions/sharding/aws_accounts.py +2 -2
  249. reconcile/gql_definitions/sharding/ocm_organization.py +63 -0
  250. reconcile/gql_definitions/skupper_network/site_controller_template.py +2 -2
  251. reconcile/gql_definitions/skupper_network/skupper_networks.py +12 -38
  252. reconcile/gql_definitions/slack_usergroups/clusters.py +2 -2
  253. reconcile/gql_definitions/slack_usergroups/permissions.py +8 -15
  254. reconcile/gql_definitions/slack_usergroups/users.py +3 -2
  255. reconcile/gql_definitions/slo_documents/__init__.py +0 -0
  256. reconcile/gql_definitions/slo_documents/slo_documents.py +142 -0
  257. reconcile/gql_definitions/status_board/__init__.py +0 -0
  258. reconcile/gql_definitions/status_board/status_board.py +163 -0
  259. reconcile/gql_definitions/statuspage/statuspages.py +56 -7
  260. reconcile/gql_definitions/templating/__init__.py +0 -0
  261. reconcile/gql_definitions/templating/template_collection.py +130 -0
  262. reconcile/gql_definitions/templating/templates.py +108 -0
  263. reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +4 -8
  264. reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +8 -8
  265. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +6 -8
  266. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +45 -56
  267. reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +4 -8
  268. reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +4 -8
  269. reconcile/gql_definitions/terraform_init/__init__.py +0 -0
  270. reconcile/gql_definitions/terraform_init/aws_accounts.py +93 -0
  271. reconcile/gql_definitions/terraform_repo/__init__.py +0 -0
  272. reconcile/gql_definitions/terraform_repo/terraform_repo.py +141 -0
  273. reconcile/gql_definitions/terraform_resources/database_access_manager.py +158 -0
  274. reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +153 -162
  275. reconcile/gql_definitions/terraform_tgw_attachments/__init__.py +0 -0
  276. reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +119 -0
  277. reconcile/gql_definitions/unleash_feature_toggles/__init__.py +0 -0
  278. reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +113 -0
  279. reconcile/gql_definitions/vault_instances/vault_instances.py +17 -50
  280. reconcile/gql_definitions/vault_policies/vault_policies.py +2 -2
  281. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +49 -12
  282. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +7 -2
  283. reconcile/integrations_manager.py +25 -13
  284. reconcile/jenkins/types.py +5 -1
  285. reconcile/jenkins_base.py +36 -0
  286. reconcile/jenkins_job_builder.py +10 -48
  287. reconcile/jenkins_job_builds_cleaner.py +40 -25
  288. reconcile/jenkins_job_cleaner.py +1 -3
  289. reconcile/jenkins_roles.py +22 -26
  290. reconcile/jenkins_webhooks.py +9 -6
  291. reconcile/jenkins_worker_fleets.py +11 -6
  292. reconcile/jira_permissions_validator.py +340 -0
  293. reconcile/jira_watcher.py +3 -5
  294. reconcile/ldap_groups/__init__.py +0 -0
  295. reconcile/ldap_groups/integration.py +279 -0
  296. reconcile/ldap_users.py +3 -0
  297. reconcile/ocm/types.py +39 -59
  298. reconcile/ocm_additional_routers.py +0 -1
  299. reconcile/ocm_addons_upgrade_tests_trigger.py +10 -15
  300. reconcile/ocm_aws_infrastructure_access.py +30 -32
  301. reconcile/ocm_clusters.py +217 -130
  302. reconcile/ocm_external_configuration_labels.py +15 -0
  303. reconcile/ocm_github_idp.py +1 -1
  304. reconcile/ocm_groups.py +25 -5
  305. reconcile/ocm_internal_notifications/__init__.py +0 -0
  306. reconcile/ocm_internal_notifications/integration.py +119 -0
  307. reconcile/ocm_labels/__init__.py +0 -0
  308. reconcile/ocm_labels/integration.py +409 -0
  309. reconcile/ocm_machine_pools.py +517 -108
  310. reconcile/ocm_upgrade_scheduler_org_updater.py +15 -11
  311. reconcile/openshift_base.py +609 -207
  312. reconcile/openshift_cluster_bots.py +344 -0
  313. reconcile/openshift_clusterrolebindings.py +15 -15
  314. reconcile/openshift_groups.py +42 -45
  315. reconcile/openshift_limitranges.py +1 -0
  316. reconcile/openshift_namespace_labels.py +22 -28
  317. reconcile/openshift_namespaces.py +22 -22
  318. reconcile/openshift_network_policies.py +4 -8
  319. reconcile/openshift_prometheus_rules.py +43 -0
  320. reconcile/openshift_resourcequotas.py +2 -16
  321. reconcile/openshift_resources.py +12 -10
  322. reconcile/openshift_resources_base.py +304 -328
  323. reconcile/openshift_rolebindings.py +18 -20
  324. reconcile/openshift_saas_deploy.py +105 -21
  325. reconcile/openshift_saas_deploy_change_tester.py +30 -35
  326. reconcile/openshift_saas_deploy_trigger_base.py +39 -36
  327. reconcile/openshift_saas_deploy_trigger_cleaner.py +41 -27
  328. reconcile/openshift_saas_deploy_trigger_configs.py +1 -2
  329. reconcile/openshift_saas_deploy_trigger_images.py +1 -2
  330. reconcile/openshift_saas_deploy_trigger_moving_commits.py +1 -2
  331. reconcile/openshift_saas_deploy_trigger_upstream_jobs.py +1 -2
  332. reconcile/openshift_serviceaccount_tokens.py +138 -74
  333. reconcile/openshift_tekton_resources.py +89 -24
  334. reconcile/openshift_upgrade_watcher.py +110 -62
  335. reconcile/openshift_users.py +16 -15
  336. reconcile/openshift_vault_secrets.py +11 -6
  337. reconcile/oum/__init__.py +0 -0
  338. reconcile/oum/base.py +387 -0
  339. reconcile/oum/labelset.py +55 -0
  340. reconcile/oum/metrics.py +71 -0
  341. reconcile/oum/models.py +69 -0
  342. reconcile/oum/providers.py +59 -0
  343. reconcile/oum/standalone.py +196 -0
  344. reconcile/prometheus_rules_tester/integration.py +31 -23
  345. reconcile/quay_base.py +4 -1
  346. reconcile/quay_membership.py +1 -2
  347. reconcile/quay_mirror.py +111 -61
  348. reconcile/quay_mirror_org.py +34 -21
  349. reconcile/quay_permissions.py +7 -3
  350. reconcile/quay_repos.py +24 -32
  351. reconcile/queries.py +263 -198
  352. reconcile/query_validator.py +3 -5
  353. reconcile/resource_scraper.py +3 -4
  354. reconcile/{template_tester.py → resource_template_tester.py} +3 -3
  355. reconcile/rhidp/__init__.py +0 -0
  356. reconcile/rhidp/common.py +214 -0
  357. reconcile/rhidp/metrics.py +20 -0
  358. reconcile/rhidp/ocm_oidc_idp/__init__.py +0 -0
  359. reconcile/rhidp/ocm_oidc_idp/base.py +221 -0
  360. reconcile/rhidp/ocm_oidc_idp/integration.py +56 -0
  361. reconcile/rhidp/ocm_oidc_idp/metrics.py +22 -0
  362. reconcile/rhidp/sso_client/__init__.py +0 -0
  363. reconcile/rhidp/sso_client/base.py +266 -0
  364. reconcile/rhidp/sso_client/integration.py +60 -0
  365. reconcile/rhidp/sso_client/metrics.py +39 -0
  366. reconcile/run_integration.py +293 -0
  367. reconcile/saas_auto_promotions_manager/integration.py +69 -24
  368. reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py +208 -0
  369. reconcile/saas_auto_promotions_manager/merge_request_manager/desired_state.py +28 -0
  370. reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request.py +3 -4
  371. reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager_v2.py +172 -0
  372. reconcile/saas_auto_promotions_manager/merge_request_manager/metrics.py +42 -0
  373. reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py +226 -0
  374. reconcile/saas_auto_promotions_manager/merge_request_manager/open_merge_requests.py +23 -0
  375. reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +108 -32
  376. reconcile/saas_auto_promotions_manager/meta.py +4 -0
  377. reconcile/saas_auto_promotions_manager/publisher.py +32 -4
  378. reconcile/saas_auto_promotions_manager/s3_exporter.py +77 -0
  379. reconcile/saas_auto_promotions_manager/subscriber.py +110 -23
  380. reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +48 -41
  381. reconcile/saas_file_validator.py +16 -6
  382. reconcile/sendgrid_teammates.py +27 -12
  383. reconcile/service_dependencies.py +0 -3
  384. reconcile/signalfx_endpoint_monitoring.py +2 -5
  385. reconcile/skupper_network/integration.py +10 -11
  386. reconcile/skupper_network/models.py +3 -5
  387. reconcile/skupper_network/reconciler.py +28 -35
  388. reconcile/skupper_network/site_controller.py +8 -8
  389. reconcile/slack_base.py +4 -7
  390. reconcile/slack_usergroups.py +249 -171
  391. reconcile/sql_query.py +324 -171
  392. reconcile/status.py +0 -1
  393. reconcile/status_board.py +275 -0
  394. reconcile/statuspage/__init__.py +0 -5
  395. reconcile/statuspage/atlassian.py +219 -80
  396. reconcile/statuspage/integration.py +9 -97
  397. reconcile/statuspage/integrations/__init__.py +0 -0
  398. reconcile/statuspage/integrations/components.py +77 -0
  399. reconcile/statuspage/integrations/maintenances.py +111 -0
  400. reconcile/statuspage/page.py +107 -72
  401. reconcile/statuspage/state.py +6 -11
  402. reconcile/statuspage/status.py +8 -12
  403. reconcile/templates/rosa-classic-cluster-creation.sh.j2 +60 -0
  404. reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +61 -0
  405. reconcile/templating/__init__.py +0 -0
  406. reconcile/templating/lib/__init__.py +0 -0
  407. reconcile/templating/lib/merge_request_manager.py +180 -0
  408. reconcile/templating/lib/model.py +20 -0
  409. reconcile/templating/lib/rendering.py +191 -0
  410. reconcile/templating/renderer.py +410 -0
  411. reconcile/templating/validator.py +153 -0
  412. reconcile/terraform_aws_route53.py +13 -10
  413. reconcile/terraform_cloudflare_dns.py +92 -122
  414. reconcile/terraform_cloudflare_resources.py +15 -13
  415. reconcile/terraform_cloudflare_users.py +27 -27
  416. reconcile/terraform_init/__init__.py +0 -0
  417. reconcile/terraform_init/integration.py +165 -0
  418. reconcile/terraform_init/merge_request.py +57 -0
  419. reconcile/terraform_init/merge_request_manager.py +102 -0
  420. reconcile/terraform_repo.py +403 -0
  421. reconcile/terraform_resources.py +266 -168
  422. reconcile/terraform_tgw_attachments.py +417 -167
  423. reconcile/terraform_users.py +40 -17
  424. reconcile/terraform_vpc_peerings.py +310 -142
  425. reconcile/terraform_vpc_resources/__init__.py +0 -0
  426. reconcile/terraform_vpc_resources/integration.py +220 -0
  427. reconcile/terraform_vpc_resources/merge_request.py +57 -0
  428. reconcile/terraform_vpc_resources/merge_request_manager.py +107 -0
  429. reconcile/typed_queries/alerting_services_settings.py +1 -2
  430. reconcile/typed_queries/app_interface_custom_messages.py +24 -0
  431. reconcile/typed_queries/app_interface_deadmanssnitch_settings.py +17 -0
  432. reconcile/typed_queries/app_interface_metrics_exporter/__init__.py +0 -0
  433. reconcile/typed_queries/app_interface_metrics_exporter/onboarding_status.py +13 -0
  434. reconcile/typed_queries/app_interface_repo_url.py +1 -2
  435. reconcile/typed_queries/app_interface_state_settings.py +1 -3
  436. reconcile/typed_queries/app_interface_vault_settings.py +1 -2
  437. reconcile/typed_queries/app_quay_repos_escalation_policies.py +14 -0
  438. reconcile/typed_queries/apps.py +11 -0
  439. reconcile/typed_queries/aws_vpc_requests.py +9 -0
  440. reconcile/typed_queries/aws_vpcs.py +12 -0
  441. reconcile/typed_queries/cloudflare.py +10 -0
  442. reconcile/typed_queries/clusters.py +7 -5
  443. reconcile/typed_queries/clusters_minimal.py +6 -5
  444. reconcile/typed_queries/clusters_with_dms.py +16 -0
  445. reconcile/typed_queries/cost_report/__init__.py +0 -0
  446. reconcile/typed_queries/cost_report/app_names.py +22 -0
  447. reconcile/typed_queries/cost_report/cost_namespaces.py +43 -0
  448. reconcile/typed_queries/cost_report/settings.py +15 -0
  449. reconcile/typed_queries/dynatrace.py +10 -0
  450. reconcile/typed_queries/dynatrace_environments.py +14 -0
  451. reconcile/typed_queries/dynatrace_token_provider_token_specs.py +14 -0
  452. reconcile/typed_queries/external_resources.py +46 -0
  453. reconcile/typed_queries/get_state_aws_account.py +20 -0
  454. reconcile/typed_queries/glitchtip.py +10 -0
  455. reconcile/typed_queries/jenkins.py +25 -0
  456. reconcile/typed_queries/jira.py +7 -0
  457. reconcile/typed_queries/jira_settings.py +16 -0
  458. reconcile/typed_queries/jiralert_settings.py +22 -0
  459. reconcile/typed_queries/ocm.py +8 -0
  460. reconcile/typed_queries/pagerduty_instances.py +2 -7
  461. reconcile/typed_queries/quay.py +23 -0
  462. reconcile/typed_queries/repos.py +20 -8
  463. reconcile/typed_queries/reserved_networks.py +12 -0
  464. reconcile/typed_queries/saas_files.py +221 -167
  465. reconcile/typed_queries/slack.py +7 -0
  466. reconcile/typed_queries/slo_documents.py +12 -0
  467. reconcile/typed_queries/status_board.py +58 -0
  468. reconcile/typed_queries/tekton_pipeline_providers.py +1 -2
  469. reconcile/typed_queries/terraform_namespaces.py +1 -2
  470. reconcile/typed_queries/terraform_tgw_attachments/__init__.py +0 -0
  471. reconcile/typed_queries/terraform_tgw_attachments/aws_accounts.py +16 -0
  472. reconcile/typed_queries/unleash.py +10 -0
  473. reconcile/typed_queries/users.py +11 -0
  474. reconcile/typed_queries/vault.py +10 -0
  475. reconcile/unleash_feature_toggles/__init__.py +0 -0
  476. reconcile/unleash_feature_toggles/integration.py +287 -0
  477. reconcile/utils/acs/__init__.py +0 -0
  478. reconcile/utils/acs/base.py +81 -0
  479. reconcile/utils/acs/notifiers.py +143 -0
  480. reconcile/utils/acs/policies.py +163 -0
  481. reconcile/utils/acs/rbac.py +277 -0
  482. reconcile/utils/aggregated_list.py +11 -9
  483. reconcile/utils/amtool.py +6 -4
  484. reconcile/utils/aws_api.py +279 -66
  485. reconcile/utils/aws_api_typed/__init__.py +0 -0
  486. reconcile/utils/aws_api_typed/account.py +23 -0
  487. reconcile/utils/aws_api_typed/api.py +273 -0
  488. reconcile/utils/aws_api_typed/dynamodb.py +16 -0
  489. reconcile/utils/aws_api_typed/iam.py +67 -0
  490. reconcile/utils/aws_api_typed/organization.py +152 -0
  491. reconcile/utils/aws_api_typed/s3.py +26 -0
  492. reconcile/utils/aws_api_typed/service_quotas.py +79 -0
  493. reconcile/utils/aws_api_typed/sts.py +36 -0
  494. reconcile/utils/aws_api_typed/support.py +79 -0
  495. reconcile/utils/aws_helper.py +42 -3
  496. reconcile/utils/batches.py +11 -0
  497. reconcile/utils/binary.py +7 -9
  498. reconcile/utils/cloud_resource_best_practice/__init__.py +0 -0
  499. reconcile/utils/cloud_resource_best_practice/aws_rds.py +66 -0
  500. reconcile/utils/clusterhealth/__init__.py +0 -0
  501. reconcile/utils/clusterhealth/providerbase.py +39 -0
  502. reconcile/utils/clusterhealth/telemeter.py +39 -0
  503. reconcile/utils/config.py +3 -4
  504. reconcile/utils/deadmanssnitch_api.py +86 -0
  505. reconcile/utils/differ.py +205 -0
  506. reconcile/utils/disabled_integrations.py +4 -6
  507. reconcile/utils/dynatrace/__init__.py +0 -0
  508. reconcile/utils/dynatrace/client.py +93 -0
  509. reconcile/utils/early_exit_cache.py +289 -0
  510. reconcile/utils/elasticsearch_exceptions.py +5 -0
  511. reconcile/utils/environ.py +2 -2
  512. reconcile/utils/exceptions.py +4 -0
  513. reconcile/utils/expiration.py +4 -8
  514. reconcile/utils/extended_early_exit.py +210 -0
  515. reconcile/utils/external_resource_spec.py +34 -12
  516. reconcile/utils/external_resources.py +48 -20
  517. reconcile/utils/filtering.py +16 -0
  518. reconcile/utils/git.py +49 -16
  519. reconcile/utils/github_api.py +10 -9
  520. reconcile/utils/gitlab_api.py +333 -190
  521. reconcile/utils/glitchtip/client.py +97 -100
  522. reconcile/utils/glitchtip/models.py +89 -11
  523. reconcile/utils/gql.py +157 -58
  524. reconcile/utils/grouping.py +17 -0
  525. reconcile/utils/helm.py +89 -18
  526. reconcile/utils/helpers.py +51 -0
  527. reconcile/utils/imap_client.py +5 -6
  528. reconcile/utils/internal_groups/__init__.py +0 -0
  529. reconcile/utils/internal_groups/client.py +160 -0
  530. reconcile/utils/internal_groups/models.py +71 -0
  531. reconcile/utils/jenkins_api.py +10 -34
  532. reconcile/utils/jinja2/__init__.py +0 -0
  533. reconcile/utils/{jinja2_ext.py → jinja2/extensions.py} +6 -4
  534. reconcile/utils/jinja2/filters.py +142 -0
  535. reconcile/utils/jinja2/utils.py +278 -0
  536. reconcile/utils/jira_client.py +165 -8
  537. reconcile/utils/jjb_client.py +47 -35
  538. reconcile/utils/jobcontroller/__init__.py +0 -0
  539. reconcile/utils/jobcontroller/controller.py +413 -0
  540. reconcile/utils/jobcontroller/models.py +195 -0
  541. reconcile/utils/jsonpath.py +4 -5
  542. reconcile/utils/jump_host.py +13 -12
  543. reconcile/utils/keycloak.py +106 -0
  544. reconcile/utils/ldap_client.py +35 -6
  545. reconcile/utils/lean_terraform_client.py +115 -6
  546. reconcile/utils/membershipsources/__init__.py +0 -0
  547. reconcile/utils/membershipsources/app_interface_resolver.py +60 -0
  548. reconcile/utils/membershipsources/models.py +91 -0
  549. reconcile/utils/membershipsources/resolver.py +110 -0
  550. reconcile/utils/merge_request_manager/__init__.py +0 -0
  551. reconcile/utils/merge_request_manager/merge_request_manager.py +99 -0
  552. reconcile/utils/merge_request_manager/parser.py +67 -0
  553. reconcile/utils/metrics.py +511 -1
  554. reconcile/utils/models.py +123 -0
  555. reconcile/utils/mr/README.md +198 -0
  556. reconcile/utils/mr/__init__.py +14 -10
  557. reconcile/utils/mr/app_interface_reporter.py +2 -2
  558. reconcile/utils/mr/aws_access.py +4 -4
  559. reconcile/utils/mr/base.py +51 -31
  560. reconcile/utils/mr/clusters_updates.py +10 -7
  561. reconcile/utils/mr/glitchtip_access_reporter.py +2 -4
  562. reconcile/utils/mr/labels.py +14 -1
  563. reconcile/utils/mr/notificator.py +1 -3
  564. reconcile/utils/mr/ocm_update_recommended_version.py +1 -2
  565. reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py +7 -3
  566. reconcile/utils/mr/promote_qontract.py +203 -0
  567. reconcile/utils/mr/user_maintenance.py +24 -4
  568. reconcile/utils/oauth2_backend_application_session.py +132 -0
  569. reconcile/utils/oc.py +194 -170
  570. reconcile/utils/oc_connection_parameters.py +40 -51
  571. reconcile/utils/oc_filters.py +11 -13
  572. reconcile/utils/oc_map.py +14 -35
  573. reconcile/utils/ocm/__init__.py +30 -1
  574. reconcile/utils/ocm/addons.py +228 -0
  575. reconcile/utils/ocm/base.py +618 -5
  576. reconcile/utils/ocm/cluster_groups.py +5 -56
  577. reconcile/utils/ocm/clusters.py +111 -99
  578. reconcile/utils/ocm/identity_providers.py +66 -0
  579. reconcile/utils/ocm/label_sources.py +75 -0
  580. reconcile/utils/ocm/labels.py +139 -54
  581. reconcile/utils/ocm/manifests.py +39 -0
  582. reconcile/utils/ocm/ocm.py +182 -928
  583. reconcile/utils/ocm/products.py +758 -0
  584. reconcile/utils/ocm/search_filters.py +20 -28
  585. reconcile/utils/ocm/service_log.py +32 -79
  586. reconcile/utils/ocm/sre_capability_labels.py +51 -0
  587. reconcile/utils/ocm/status_board.py +66 -0
  588. reconcile/utils/ocm/subscriptions.py +49 -59
  589. reconcile/utils/ocm/syncsets.py +39 -0
  590. reconcile/utils/ocm/upgrades.py +181 -0
  591. reconcile/utils/ocm_base_client.py +71 -36
  592. reconcile/utils/openshift_resource.py +113 -67
  593. reconcile/utils/output.py +18 -11
  594. reconcile/utils/pagerduty_api.py +16 -10
  595. reconcile/utils/parse_dhms_duration.py +13 -1
  596. reconcile/utils/prometheus.py +123 -0
  597. reconcile/utils/promotion_state.py +56 -19
  598. reconcile/utils/promtool.py +5 -8
  599. reconcile/utils/quay_api.py +13 -25
  600. reconcile/utils/raw_github_api.py +3 -5
  601. reconcile/utils/repo_owners.py +2 -8
  602. reconcile/utils/rest_api_base.py +126 -0
  603. reconcile/utils/rosa/__init__.py +0 -0
  604. reconcile/utils/rosa/rosa_cli.py +310 -0
  605. reconcile/utils/rosa/session.py +201 -0
  606. reconcile/utils/ruamel.py +16 -0
  607. reconcile/utils/runtime/__init__.py +0 -1
  608. reconcile/utils/runtime/desired_state_diff.py +9 -20
  609. reconcile/utils/runtime/environment.py +33 -8
  610. reconcile/utils/runtime/integration.py +28 -12
  611. reconcile/utils/runtime/meta.py +1 -3
  612. reconcile/utils/runtime/runner.py +8 -11
  613. reconcile/utils/runtime/sharding.py +93 -36
  614. reconcile/utils/saasherder/__init__.py +1 -1
  615. reconcile/utils/saasherder/interfaces.py +143 -138
  616. reconcile/utils/saasherder/models.py +201 -43
  617. reconcile/utils/saasherder/saasherder.py +508 -378
  618. reconcile/utils/secret_reader.py +22 -27
  619. reconcile/utils/semver_helper.py +15 -1
  620. reconcile/utils/slack_api.py +124 -36
  621. reconcile/utils/smtp_client.py +1 -2
  622. reconcile/utils/sqs_gateway.py +10 -6
  623. reconcile/utils/state.py +276 -127
  624. reconcile/utils/terraform/config_client.py +6 -7
  625. reconcile/utils/terraform_client.py +284 -125
  626. reconcile/utils/terrascript/cloudflare_client.py +38 -17
  627. reconcile/utils/terrascript/cloudflare_resources.py +67 -18
  628. reconcile/utils/terrascript/models.py +2 -3
  629. reconcile/utils/terrascript/resources.py +1 -2
  630. reconcile/utils/terrascript_aws_client.py +1292 -540
  631. reconcile/utils/three_way_diff_strategy.py +157 -0
  632. reconcile/utils/unleash/__init__.py +11 -0
  633. reconcile/utils/{unleash.py → unleash/client.py} +35 -29
  634. reconcile/utils/unleash/server.py +145 -0
  635. reconcile/utils/vault.py +42 -32
  636. reconcile/utils/vaultsecretref.py +2 -4
  637. reconcile/utils/vcs.py +250 -0
  638. reconcile/vault_replication.py +38 -31
  639. reconcile/vpc_peerings_validator.py +82 -13
  640. tools/app_interface_metrics_exporter.py +70 -0
  641. tools/app_interface_reporter.py +44 -157
  642. tools/cli_commands/container_images_report.py +154 -0
  643. tools/cli_commands/cost_report/__init__.py +0 -0
  644. tools/cli_commands/cost_report/aws.py +137 -0
  645. tools/cli_commands/cost_report/cost_management_api.py +155 -0
  646. tools/cli_commands/cost_report/model.py +49 -0
  647. tools/cli_commands/cost_report/openshift.py +166 -0
  648. tools/cli_commands/cost_report/openshift_cost_optimization.py +187 -0
  649. tools/cli_commands/cost_report/response.py +124 -0
  650. tools/cli_commands/cost_report/util.py +72 -0
  651. tools/cli_commands/cost_report/view.py +524 -0
  652. tools/cli_commands/erv2.py +620 -0
  653. tools/cli_commands/gpg_encrypt.py +5 -8
  654. tools/cli_commands/systems_and_tools.py +489 -0
  655. tools/glitchtip_access_revalidation.py +1 -1
  656. tools/qontract_cli.py +2301 -673
  657. tools/saas_metrics_exporter/__init__.py +0 -0
  658. tools/saas_metrics_exporter/commit_distance/__init__.py +0 -0
  659. tools/saas_metrics_exporter/commit_distance/channel.py +63 -0
  660. tools/saas_metrics_exporter/commit_distance/commit_distance.py +103 -0
  661. tools/saas_metrics_exporter/commit_distance/metrics.py +19 -0
  662. tools/saas_metrics_exporter/main.py +99 -0
  663. tools/saas_promotion_state/__init__.py +0 -0
  664. tools/saas_promotion_state/saas_promotion_state.py +105 -0
  665. tools/sd_app_sre_alert_report.py +145 -0
  666. tools/template_validation.py +107 -0
  667. e2e_tests/cli.py +0 -83
  668. e2e_tests/create_namespace.py +0 -43
  669. e2e_tests/dedicated_admin_rolebindings.py +0 -44
  670. e2e_tests/dedicated_admin_test_base.py +0 -39
  671. e2e_tests/default_network_policies.py +0 -47
  672. e2e_tests/default_project_labels.py +0 -52
  673. e2e_tests/network_policy_test_base.py +0 -17
  674. e2e_tests/test_base.py +0 -56
  675. qontract_reconcile-0.10.0.dist-info/LICENSE +0 -201
  676. qontract_reconcile-0.10.0.dist-info/METADATA +0 -63
  677. qontract_reconcile-0.10.0.dist-info/RECORD +0 -586
  678. qontract_reconcile-0.10.0.dist-info/top_level.txt +0 -4
  679. reconcile/ecr_mirror.py +0 -152
  680. reconcile/github_scanner.py +0 -74
  681. reconcile/gitlab_integrations.py +0 -63
  682. reconcile/gql_definitions/ocm_oidc_idp/clusters.py +0 -195
  683. reconcile/gql_definitions/ocp_release_mirror/ocp_release_mirror.py +0 -287
  684. reconcile/integrations_validator.py +0 -18
  685. reconcile/jenkins_plugins.py +0 -129
  686. reconcile/kafka_clusters.py +0 -208
  687. reconcile/ocm_cluster_admin.py +0 -42
  688. reconcile/ocm_oidc_idp.py +0 -198
  689. reconcile/ocp_release_mirror.py +0 -373
  690. reconcile/prometheus_rules_tester_old.py +0 -436
  691. reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager.py +0 -279
  692. reconcile/saas_auto_promotions_manager/utils/vcs.py +0 -141
  693. reconcile/sentry_config.py +0 -613
  694. reconcile/sentry_helper.py +0 -69
  695. reconcile/test/conftest.py +0 -187
  696. reconcile/test/fixtures.py +0 -24
  697. reconcile/test/saas_auto_promotions_manager/conftest.py +0 -69
  698. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py +0 -110
  699. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/data_keys.py +0 -10
  700. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_housekeeping.py +0 -200
  701. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py +0 -151
  702. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +0 -63
  703. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/data_keys.py +0 -4
  704. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_multiple_namespaces.py +0 -46
  705. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_namespace.py +0 -94
  706. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_target.py +0 -44
  707. reconcile/test/saas_auto_promotions_manager/subscriber/conftest.py +0 -74
  708. reconcile/test/saas_auto_promotions_manager/subscriber/data_keys.py +0 -11
  709. reconcile/test/saas_auto_promotions_manager/subscriber/test_content_hash.py +0 -155
  710. reconcile/test/saas_auto_promotions_manager/subscriber/test_diff.py +0 -173
  711. reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_config_hash.py +0 -226
  712. reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_moving_ref.py +0 -224
  713. reconcile/test/saas_auto_promotions_manager/subscriber/test_single_channel_with_single_publisher.py +0 -350
  714. reconcile/test/saas_auto_promotions_manager/test_integration_test.py +0 -129
  715. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_multiple_publishers_for_single_channel.py +0 -70
  716. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_use_target_config_hash.py +0 -63
  717. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_with_auto_promote.py +0 -74
  718. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_without_auto_promote.py +0 -65
  719. reconcile/test/test_aggregated_list.py +0 -237
  720. reconcile/test/test_amtool.py +0 -37
  721. reconcile/test/test_auto_promoter.py +0 -295
  722. reconcile/test/test_aws_ami_share.py +0 -68
  723. reconcile/test/test_aws_iam_keys.py +0 -70
  724. reconcile/test/test_aws_iam_password_reset.py +0 -35
  725. reconcile/test/test_aws_support_cases_sos.py +0 -23
  726. reconcile/test/test_checkpoint.py +0 -178
  727. reconcile/test/test_cli.py +0 -41
  728. reconcile/test/test_closedbox_endpoint_monitoring.py +0 -207
  729. reconcile/test/test_gabi_authorized_users.py +0 -72
  730. reconcile/test/test_github_org.py +0 -154
  731. reconcile/test/test_github_repo_invites.py +0 -123
  732. reconcile/test/test_gitlab_housekeeping.py +0 -88
  733. reconcile/test/test_gitlab_labeler.py +0 -129
  734. reconcile/test/test_gitlab_members.py +0 -283
  735. reconcile/test/test_instrumented_wrappers.py +0 -18
  736. reconcile/test/test_integrations_manager.py +0 -995
  737. reconcile/test/test_jenkins_worker_fleets.py +0 -55
  738. reconcile/test/test_jump_host.py +0 -117
  739. reconcile/test/test_ldap_users.py +0 -123
  740. reconcile/test/test_make.py +0 -28
  741. reconcile/test/test_ocm_additional_routers.py +0 -134
  742. reconcile/test/test_ocm_addons_upgrade_scheduler_org.py +0 -149
  743. reconcile/test/test_ocm_clusters.py +0 -598
  744. reconcile/test/test_ocm_clusters_manifest_updates.py +0 -89
  745. reconcile/test/test_ocm_oidc_idp.py +0 -315
  746. reconcile/test/test_ocm_update_recommended_version.py +0 -145
  747. reconcile/test/test_ocm_upgrade_scheduler.py +0 -614
  748. reconcile/test/test_ocm_upgrade_scheduler_org_updater.py +0 -129
  749. reconcile/test/test_openshift_base.py +0 -730
  750. reconcile/test/test_openshift_namespace_labels.py +0 -345
  751. reconcile/test/test_openshift_namespaces.py +0 -256
  752. reconcile/test/test_openshift_resource.py +0 -415
  753. reconcile/test/test_openshift_resources_base.py +0 -440
  754. reconcile/test/test_openshift_saas_deploy_change_tester.py +0 -310
  755. reconcile/test/test_openshift_tekton_resources.py +0 -253
  756. reconcile/test/test_openshift_upgrade_watcher.py +0 -146
  757. reconcile/test/test_prometheus_rules_tester.py +0 -151
  758. reconcile/test/test_prometheus_rules_tester_old.py +0 -77
  759. reconcile/test/test_quay_membership.py +0 -86
  760. reconcile/test/test_quay_mirror.py +0 -109
  761. reconcile/test/test_quay_mirror_org.py +0 -70
  762. reconcile/test/test_quay_repos.py +0 -59
  763. reconcile/test/test_queries.py +0 -53
  764. reconcile/test/test_repo_owners.py +0 -47
  765. reconcile/test/test_requests_sender.py +0 -139
  766. reconcile/test/test_saasherder.py +0 -1074
  767. reconcile/test/test_saasherder_allowed_secret_paths.py +0 -127
  768. reconcile/test/test_secret_reader.py +0 -153
  769. reconcile/test/test_slack_base.py +0 -185
  770. reconcile/test/test_slack_usergroups.py +0 -744
  771. reconcile/test/test_sql_query.py +0 -19
  772. reconcile/test/test_terraform_cloudflare_dns.py +0 -117
  773. reconcile/test/test_terraform_cloudflare_resources.py +0 -106
  774. reconcile/test/test_terraform_cloudflare_users.py +0 -749
  775. reconcile/test/test_terraform_resources.py +0 -257
  776. reconcile/test/test_terraform_tgw_attachments.py +0 -631
  777. reconcile/test/test_terraform_users.py +0 -57
  778. reconcile/test/test_terraform_vpc_peerings.py +0 -499
  779. reconcile/test/test_terraform_vpc_peerings_build_desired_state.py +0 -1061
  780. reconcile/test/test_unleash.py +0 -138
  781. reconcile/test/test_utils_aws_api.py +0 -240
  782. reconcile/test/test_utils_aws_helper.py +0 -80
  783. reconcile/test/test_utils_cluster_version_data.py +0 -177
  784. reconcile/test/test_utils_data_structures.py +0 -13
  785. reconcile/test/test_utils_disabled_integrations.py +0 -86
  786. reconcile/test/test_utils_expiration.py +0 -109
  787. reconcile/test/test_utils_external_resource_spec.py +0 -383
  788. reconcile/test/test_utils_external_resources.py +0 -247
  789. reconcile/test/test_utils_github_api.py +0 -73
  790. reconcile/test/test_utils_gitlab_api.py +0 -20
  791. reconcile/test/test_utils_gpg.py +0 -69
  792. reconcile/test/test_utils_gql.py +0 -81
  793. reconcile/test/test_utils_helm.py +0 -306
  794. reconcile/test/test_utils_helpers.py +0 -55
  795. reconcile/test/test_utils_imap_client.py +0 -65
  796. reconcile/test/test_utils_jjb_client.py +0 -52
  797. reconcile/test/test_utils_jsonpath.py +0 -286
  798. reconcile/test/test_utils_ldap_client.py +0 -51
  799. reconcile/test/test_utils_mr.py +0 -226
  800. reconcile/test/test_utils_mr_clusters_updates.py +0 -77
  801. reconcile/test/test_utils_oc.py +0 -984
  802. reconcile/test/test_utils_ocm.py +0 -110
  803. reconcile/test/test_utils_pagerduty_api.py +0 -251
  804. reconcile/test/test_utils_parse_dhms_duration.py +0 -34
  805. reconcile/test/test_utils_password_validator.py +0 -155
  806. reconcile/test/test_utils_quay_api.py +0 -86
  807. reconcile/test/test_utils_semver_helper.py +0 -19
  808. reconcile/test/test_utils_sharding.py +0 -56
  809. reconcile/test/test_utils_slack_api.py +0 -439
  810. reconcile/test/test_utils_smtp_client.py +0 -73
  811. reconcile/test/test_utils_state.py +0 -256
  812. reconcile/test/test_utils_terraform.py +0 -13
  813. reconcile/test/test_utils_terraform_client.py +0 -585
  814. reconcile/test/test_utils_terraform_config_client.py +0 -219
  815. reconcile/test/test_utils_terrascript_aws_client.py +0 -277
  816. reconcile/test/test_utils_terrascript_cloudflare_client.py +0 -597
  817. reconcile/test/test_utils_terrascript_cloudflare_resources.py +0 -26
  818. reconcile/test/test_vault_replication.py +0 -515
  819. reconcile/test/test_vault_utils.py +0 -47
  820. reconcile/test/test_version_bump.py +0 -18
  821. reconcile/test/test_vpc_peerings_validator.py +0 -103
  822. reconcile/test/test_wrong_region.py +0 -78
  823. reconcile/typed_queries/glitchtip_settings.py +0 -18
  824. reconcile/typed_queries/ocp_release_mirror.py +0 -11
  825. reconcile/unleash_watcher.py +0 -120
  826. reconcile/utils/git_secrets.py +0 -63
  827. reconcile/utils/mr/auto_promoter.py +0 -218
  828. reconcile/utils/sentry_client.py +0 -383
  829. release/test_version.py +0 -50
  830. release/version.py +0 -100
  831. tools/test/test_qontract_cli.py +0 -60
  832. tools/test/test_sre_checkpoints.py +0 -79
  833. /e2e_tests/__init__.py → /reconcile/aus/upgrades.py +0 -0
  834. /reconcile/{gql_definitions/ocp_release_mirror → aws_account_manager}/__init__.py +0 -0
  835. /reconcile/{test → aws_ami_cleanup}/__init__.py +0 -0
  836. /reconcile/{test/saas_auto_promotions_manager → aws_cloudwatch_log_retention}/__init__.py +0 -0
  837. /reconcile/{test/saas_auto_promotions_manager/merge_request_manager → aws_saml_idp}/__init__.py +0 -0
  838. /reconcile/{test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager → aws_saml_roles}/__init__.py +0 -0
  839. /reconcile/{test/saas_auto_promotions_manager/merge_request_manager/renderer → aws_version_sync}/__init__.py +0 -0
  840. /reconcile/{test/saas_auto_promotions_manager/subscriber → aws_version_sync/merge_request_manager}/__init__.py +0 -0
  841. /reconcile/{test/saas_auto_promotions_manager/utils → cluster_auth_rhidp}/__init__.py +0 -0
  842. /reconcile/{test/saas_auto_promotions_manager/utils/saas_files_inventory → dynatrace_token_provider}/__init__.py +0 -0
  843. {release → reconcile/endpoints_discovery}/__init__.py +0 -0
  844. {tools/test → reconcile/external_resources}/__init__.py +0 -0
@@ -1,10 +1,8 @@
1
1
  import json
2
2
  import logging
3
3
  import sys
4
- from typing import (
5
- Any,
6
- Optional,
7
- )
4
+ from collections.abc import Callable, Iterable, Mapping
5
+ from typing import Any, TypedDict
8
6
 
9
7
  import reconcile.utils.terraform_client as terraform
10
8
  import reconcile.utils.terrascript_aws_client as terrascript
@@ -15,11 +13,16 @@ from reconcile.utils import (
15
13
  )
16
14
  from reconcile.utils.aws_api import AWSApi
17
15
  from reconcile.utils.defer import defer
16
+ from reconcile.utils.extended_early_exit import (
17
+ ExtendedEarlyExitRunnerResult,
18
+ extended_early_exit_run,
19
+ )
18
20
  from reconcile.utils.ocm import (
19
21
  OCM,
20
22
  OCMMap,
21
23
  )
22
24
  from reconcile.utils.semver_helper import make_semver
25
+ from reconcile.utils.unleash.client import get_feature_toggle_state
23
26
 
24
27
  QONTRACT_INTEGRATION = "terraform_vpc_peerings"
25
28
  QONTRACT_INTEGRATION_VERSION = make_semver(0, 1, 0)
@@ -29,7 +32,11 @@ class BadTerraformPeeringState(Exception):
29
32
  pass
30
33
 
31
34
 
32
- def find_matching_peering(from_cluster, to_cluster, desired_provider):
35
+ def find_matching_peering(
36
+ from_cluster: Mapping[str, Any],
37
+ to_cluster: Mapping[str, Any],
38
+ desired_provider: str,
39
+ ) -> Mapping[str, Any] | None:
33
40
  """
34
41
  Ensures there is a matching peering with the desired provider type
35
42
  going from the destination (to) cluster back to this one (from)
@@ -37,7 +44,7 @@ def find_matching_peering(from_cluster, to_cluster, desired_provider):
37
44
  peering_info = to_cluster["peering"]
38
45
  peer_connections = peering_info["connections"]
39
46
  for peer_connection in peer_connections:
40
- if not peer_connection["provider"] == desired_provider:
47
+ if peer_connection["provider"] != desired_provider:
41
48
  continue
42
49
  if not peer_connection["cluster"]:
43
50
  continue
@@ -47,8 +54,8 @@ def find_matching_peering(from_cluster, to_cluster, desired_provider):
47
54
 
48
55
 
49
56
  def _get_default_management_account(
50
- cluster: dict[str, Any]
51
- ) -> Optional[dict[str, Any]]:
57
+ cluster: Mapping[str, Any],
58
+ ) -> Mapping[str, Any] | None:
52
59
  cluster_infra_accounts = cluster["awsInfrastructureManagementAccounts"]
53
60
  for infra_account_def in cluster_infra_accounts or []:
54
61
  if (
@@ -60,13 +67,29 @@ def _get_default_management_account(
60
67
 
61
68
 
62
69
  def _build_infrastructure_assume_role(
63
- account: dict[str, Any], cluster: dict[str, Any], ocm: OCM
64
- ) -> Optional[dict[str, Any]]:
65
- assume_role = ocm.get_aws_infrastructure_access_terraform_assume_role(
66
- cluster["name"],
67
- account["uid"],
68
- account["terraformUsername"],
69
- )
70
+ account: Mapping[str, Any],
71
+ cluster: Mapping[str, Any],
72
+ ocm: OCM | None,
73
+ provided_assume_role: str | None,
74
+ ) -> dict[str, Any] | None:
75
+ if provided_assume_role:
76
+ assume_role = provided_assume_role
77
+ elif cluster["spec"].get("account"):
78
+ cluster_account = cluster["spec"].get("account")
79
+ return {
80
+ "name": cluster_account["name"],
81
+ "uid": cluster_account["uid"],
82
+ "terraformUsername": cluster_account["terraformUsername"],
83
+ "automationToken": cluster_account["automationToken"],
84
+ "assume_region": cluster["spec"]["region"],
85
+ "assume_cidr": cluster["network"]["vpc"],
86
+ }
87
+ elif ocm is not None:
88
+ assume_role = ocm.get_aws_infrastructure_access_terraform_assume_role(
89
+ cluster["name"],
90
+ account["uid"],
91
+ account["terraformUsername"],
92
+ )
70
93
  if assume_role:
71
94
  return {
72
95
  "name": account["name"],
@@ -81,11 +104,12 @@ def _build_infrastructure_assume_role(
81
104
 
82
105
 
83
106
  def aws_assume_roles_for_cluster_vpc_peering(
84
- requester_cluster: dict[str, Any],
85
- accepter_connection: dict[str, Any],
86
- accepter_cluster: dict[str, Any],
87
- ocm: OCM,
88
- ) -> tuple[dict[str, Any], dict[str, Any]]:
107
+ requester_connection: Mapping[str, Any],
108
+ requester_cluster: Mapping[str, Any],
109
+ accepter_connection: Mapping[str, Any],
110
+ accepter_cluster: Mapping[str, Any],
111
+ ocm: OCM | None,
112
+ ) -> tuple[str, dict[str, Any], dict[str, Any]]:
89
113
  # check if dedicated infra accounts have been declared on the
90
114
  # accepters peering connection or on the accepters cluster
91
115
  allowed_accounts = {
@@ -96,21 +120,21 @@ def aws_assume_roles_for_cluster_vpc_peering(
96
120
 
97
121
  # check if a dedicated infra accounts have been declared on the
98
122
  # accepters peering connection
99
- account = accepter_connection["awsInfrastructureManagementAccount"]
100
- if account and account["name"] not in allowed_accounts:
123
+ infra_account = accepter_connection["awsInfrastructureManagementAccount"]
124
+ if infra_account and infra_account["name"] not in allowed_accounts:
101
125
  raise BadTerraformPeeringState(
102
126
  "[account_not_allowed] "
103
- f"account {account['name']} used on the peering accepter of "
127
+ f"account {infra_account['name']} used on the peering accepter of "
104
128
  f"cluster {accepter_cluster['name']} is not listed as a "
105
129
  "network-mgmt in awsInfrastructureManagementAccounts"
106
130
  )
107
131
 
108
- if not account:
132
+ if not infra_account:
109
133
  # look for a network-mgmt account marked as default on the accepters
110
134
  # clusters awsInfrastructureManagementAccounts
111
- account = _get_default_management_account(accepter_cluster)
135
+ infra_account = _get_default_management_account(accepter_cluster)
112
136
 
113
- if not account:
137
+ if not infra_account:
114
138
  raise BadTerraformPeeringState(
115
139
  f"[no_account_available] unable to find infra account "
116
140
  f"for {accepter_cluster['name']} to manage the VPC peering "
@@ -119,27 +143,34 @@ def aws_assume_roles_for_cluster_vpc_peering(
119
143
 
120
144
  # a dedicated infra account was found on the accepter side
121
145
  # let's use it for both legs
122
- req_aws = _build_infrastructure_assume_role(account, requester_cluster, ocm)
146
+ req_aws = _build_infrastructure_assume_role(
147
+ infra_account, requester_cluster, ocm, requester_connection.get("assumeRole")
148
+ )
123
149
  if req_aws is None:
124
150
  raise BadTerraformPeeringState(
125
151
  f"[assume_role_not_found] unable to find assume role "
126
- f"on cluster-vpc-requester for account {account['name']} and "
152
+ f"on cluster-vpc-requester for account {infra_account['name']} and "
127
153
  f"cluster {requester_cluster['name']} "
128
154
  )
129
- acc_aws = _build_infrastructure_assume_role(account, accepter_cluster, ocm)
155
+ acc_aws = _build_infrastructure_assume_role(
156
+ infra_account, accepter_cluster, ocm, accepter_connection.get("assumeRole")
157
+ )
130
158
  if acc_aws is None:
131
159
  raise BadTerraformPeeringState(
132
160
  f"[assume_role_not_found] unable to find assume role "
133
- f"on cluster-vpc-accepter for account {account['name']} and "
161
+ f"on cluster-vpc-accepter for account {infra_account['name']} and "
134
162
  f"cluster {accepter_cluster['name']} "
135
163
  )
136
164
 
137
- return req_aws, acc_aws
165
+ return infra_account["name"], req_aws, acc_aws
138
166
 
139
167
 
140
168
  def build_desired_state_single_cluster(
141
- cluster_info, ocm: OCM, awsapi: AWSApi, account_filter: Optional[str]
142
- ):
169
+ cluster_info: Mapping[str, Any],
170
+ ocm: OCM | None,
171
+ awsapi: AWSApi,
172
+ account_filter: str | None,
173
+ ) -> list[dict[str, Any]]:
143
174
  cluster_name = cluster_info["name"]
144
175
 
145
176
  peerings = []
@@ -169,32 +200,31 @@ def build_desired_state_single_cluster(
169
200
 
170
201
  accepter_manage_routes = peer_info.get("manageRoutes")
171
202
 
172
- req_aws, acc_aws = aws_assume_roles_for_cluster_vpc_peering(
173
- cluster_info, peer_info, peer_cluster, ocm
203
+ infra_account_name, req_aws, acc_aws = aws_assume_roles_for_cluster_vpc_peering(
204
+ peer_connection, cluster_info, peer_info, peer_cluster, ocm
174
205
  )
175
206
 
176
207
  # filter on account
177
- if account_filter and acc_aws["name"] != account_filter:
208
+ if (
209
+ account_filter
210
+ and acc_aws["name"] != account_filter
211
+ and infra_account_name != account_filter
212
+ ):
178
213
  continue
179
214
 
180
- # verify that the infra mgmt account for both sides of a peering is the same
181
- # this is a restriction we might lift in the future but it
182
- # requires work in `populate_vpc_peerings` where the tf resources are hooked up
183
- if req_aws["name"] != acc_aws["name"]:
184
- raise BadTerraformPeeringState(
185
- f"different infra mgmt accounts for peering "
186
- f"requester ({cluster_name} - {req_aws['name']}) and "
187
- f"accepter ({peer_connection_name} - {acc_aws['name']}) "
188
- "are not suppored"
215
+ requester_vpc_id, requester_route_table_ids, _, api_security_group_id = (
216
+ awsapi.get_cluster_vpc_details(
217
+ req_aws,
218
+ route_tables=requester_manage_routes,
219
+ hcp_vpc_endpoint_sg=_private_hosted_control_plane(cluster_info),
189
220
  )
190
-
191
- requester_vpc_id, requester_route_table_ids, _ = awsapi.get_cluster_vpc_details(
192
- req_aws, route_tables=requester_manage_routes
193
221
  )
194
222
  if requester_vpc_id is None:
195
- raise BadTerraformPeeringState(
196
- f"[{cluster_name}] could not find VPC ID for cluster"
223
+ logging.warning(
224
+ f"[{cluster_name}] could not find VPC ID for cluster. "
225
+ f"Skipping {peer_connection_provider} connection {peer_connection['name']}"
197
226
  )
227
+ continue
198
228
 
199
229
  requester = {
200
230
  "cidr_block": cluster_info["network"]["vpc"],
@@ -202,28 +232,42 @@ def build_desired_state_single_cluster(
202
232
  "vpc_id": requester_vpc_id,
203
233
  "route_table_ids": requester_route_table_ids,
204
234
  "account": req_aws,
235
+ "api_security_group_id": api_security_group_id,
205
236
  }
206
237
 
207
- accepter_vpc_id, accepter_route_table_ids, _ = awsapi.get_cluster_vpc_details(
208
- acc_aws, route_tables=accepter_manage_routes
238
+ (
239
+ accepter_vpc_id,
240
+ accepter_route_table_ids,
241
+ _,
242
+ api_security_group_id,
243
+ ) = awsapi.get_cluster_vpc_details(
244
+ acc_aws,
245
+ route_tables=accepter_manage_routes,
246
+ hcp_vpc_endpoint_sg=_private_hosted_control_plane(peer_cluster),
209
247
  )
210
248
  if accepter_vpc_id is None:
211
- raise BadTerraformPeeringState(
212
- f"[{peer_cluster_name}] could not find VPC ID for cluster"
249
+ logging.warning(
250
+ f"[{peer_cluster_name}] could not find VPC ID for cluster. "
251
+ f"Skipping {peer_info['provider']} connection {peer_info['name']}"
213
252
  )
253
+ continue
214
254
 
215
- requester["peer_owner_id"] = acc_aws["assume_role"].split(":")[4]
255
+ requester["peer_owner_id"] = acc_aws["uid"]
256
+ if acc_aws.get("assume_role"):
257
+ requester["peer_owner_id"] = acc_aws["assume_role"].split(":")[4]
216
258
  accepter = {
217
259
  "cidr_block": peer_cluster["network"]["vpc"],
218
260
  "region": peer_cluster["spec"]["region"],
219
261
  "vpc_id": accepter_vpc_id,
220
262
  "route_table_ids": accepter_route_table_ids,
221
263
  "account": acc_aws,
264
+ "api_security_group_id": api_security_group_id,
222
265
  }
223
266
 
224
267
  item = {
225
268
  "connection_provider": peer_connection_provider,
226
269
  "connection_name": peer_connection_name,
270
+ "infra_account_name": infra_account_name,
227
271
  "requester": requester,
228
272
  "accepter": accepter,
229
273
  "deleted": peer_connection.get("delete", False),
@@ -234,8 +278,11 @@ def build_desired_state_single_cluster(
234
278
 
235
279
 
236
280
  def build_desired_state_all_clusters(
237
- clusters, ocm_map: OCMMap, awsapi: AWSApi, account_filter: Optional[str]
238
- ):
281
+ clusters: Iterable[Mapping[str, Any]],
282
+ ocm_map: OCMMap | None,
283
+ awsapi: AWSApi,
284
+ account_filter: str | None,
285
+ ) -> tuple[list[dict[str, Any]], bool]:
239
286
  """
240
287
  Fetch state for VPC peerings between two OCM clusters
241
288
  """
@@ -245,7 +292,7 @@ def build_desired_state_all_clusters(
245
292
  for cluster_info in clusters:
246
293
  try:
247
294
  cluster = cluster_info["name"]
248
- ocm = ocm_map.get(cluster)
295
+ ocm = None if ocm_map is None else ocm_map.get(cluster)
249
296
  items = build_desired_state_single_cluster(
250
297
  cluster_info, ocm, awsapi, account_filter
251
298
  )
@@ -258,8 +305,11 @@ def build_desired_state_all_clusters(
258
305
 
259
306
 
260
307
  def build_desired_state_vpc_mesh_single_cluster(
261
- cluster_info, ocm: OCM, awsapi: AWSApi, account_filter: Optional[str]
262
- ):
308
+ cluster_info: Mapping[str, Any],
309
+ ocm: OCM | None,
310
+ awsapi: AWSApi,
311
+ account_filter: str | None,
312
+ ) -> list[dict[str, Any]]:
263
313
  desired_state = []
264
314
 
265
315
  cluster = cluster_info["name"]
@@ -268,7 +318,7 @@ def build_desired_state_vpc_mesh_single_cluster(
268
318
  for peer_connection in peer_connections:
269
319
  # We only care about account-vpc-mesh peering providers
270
320
  peer_connection_provider = peer_connection["provider"]
271
- if not peer_connection_provider == "account-vpc-mesh":
321
+ if peer_connection_provider != "account-vpc-mesh":
272
322
  continue
273
323
  # filter on account
274
324
  account = peer_connection["account"]
@@ -281,28 +331,45 @@ def build_desired_state_vpc_mesh_single_cluster(
281
331
  "region": cluster_info["spec"]["region"],
282
332
  }
283
333
 
334
+ cluster_account = account
284
335
  # assume_role is the role to assume to provision the peering
285
336
  # connection request, through the accepter AWS account.
286
- account[
287
- "assume_role"
288
- ] = ocm.get_aws_infrastructure_access_terraform_assume_role(
289
- cluster, account["uid"], account["terraformUsername"]
290
- )
337
+ provided_assume_role = peer_connection.get("assumeRole")
338
+ if provided_assume_role:
339
+ cluster_account["assume_role"] = provided_assume_role
340
+ elif cluster_info["spec"].get("account"):
341
+ cluster_account = cluster_info["spec"].get("account")
342
+ elif ocm is not None:
343
+ cluster_account["assume_role"] = (
344
+ ocm.get_aws_infrastructure_access_terraform_assume_role(
345
+ cluster, account["uid"], account["terraformUsername"]
346
+ )
347
+ )
291
348
  account["assume_region"] = requester["region"]
292
- account["assume_cidr"] = requester["cidr_block"]
293
- requester_vpc_id, requester_route_table_ids, _ = awsapi.get_cluster_vpc_details(
294
- account, route_tables=peer_connection.get("manageRoutes")
349
+ cluster_account["assume_region"] = requester["region"]
350
+ cluster_account["assume_cidr"] = requester["cidr_block"]
351
+ (
352
+ requester_vpc_id,
353
+ requester_route_table_ids,
354
+ _,
355
+ api_security_group_id,
356
+ ) = awsapi.get_cluster_vpc_details(
357
+ cluster_account,
358
+ route_tables=peer_connection.get("manageRoutes"),
359
+ hcp_vpc_endpoint_sg=_private_hosted_control_plane(cluster_info),
295
360
  )
296
361
 
297
362
  if requester_vpc_id is None:
298
- raise BadTerraformPeeringState(
299
- f"{cluster} could not find VPC ID for cluster and "
300
- f"peer account {account}"
363
+ logging.warning(
364
+ f"[{cluster}] could not find VPC ID for cluster and peer account {account}. "
365
+ f"Skipping {peer_connection_provider} connection {peer_connection['name']}"
301
366
  )
367
+ continue
302
368
 
303
369
  requester["vpc_id"] = requester_vpc_id
304
370
  requester["route_table_ids"] = requester_route_table_ids
305
- requester["account"] = account
371
+ requester["account"] = cluster_account
372
+ requester["api_security_group_id"] = api_security_group_id
306
373
 
307
374
  account_vpcs = awsapi.get_vpcs_details(
308
375
  account,
@@ -324,6 +391,7 @@ def build_desired_state_vpc_mesh_single_cluster(
324
391
  item = {
325
392
  "connection_provider": peer_connection_provider,
326
393
  "connection_name": connection_name,
394
+ "infra_account_name": account["name"],
327
395
  "requester": requester,
328
396
  "accepter": accepter,
329
397
  "deleted": peer_connection.get("delete", False),
@@ -334,8 +402,11 @@ def build_desired_state_vpc_mesh_single_cluster(
334
402
 
335
403
 
336
404
  def build_desired_state_vpc_mesh(
337
- clusters, ocm_map: OCMMap, awsapi: AWSApi, account_filter: Optional[str]
338
- ):
405
+ clusters: Iterable[Mapping[str, Any]],
406
+ ocm_map: OCMMap | None,
407
+ awsapi: AWSApi,
408
+ account_filter: str | None,
409
+ ) -> tuple[list[dict[str, Any]], bool]:
339
410
  """
340
411
  Fetch state for VPC peerings between a cluster and all VPCs in an account
341
412
  """
@@ -345,7 +416,7 @@ def build_desired_state_vpc_mesh(
345
416
  for cluster_info in clusters:
346
417
  try:
347
418
  cluster = cluster_info["name"]
348
- ocm = ocm_map.get(cluster)
419
+ ocm = None if ocm_map is None else ocm_map.get(cluster)
349
420
  items = build_desired_state_vpc_mesh_single_cluster(
350
421
  cluster_info, ocm, awsapi, account_filter
351
422
  )
@@ -358,8 +429,11 @@ def build_desired_state_vpc_mesh(
358
429
 
359
430
 
360
431
  def build_desired_state_vpc_single_cluster(
361
- cluster_info, ocm: Optional[OCM], awsapi: AWSApi, account_filter: Optional[str]
362
- ):
432
+ cluster_info: Mapping[str, Any],
433
+ ocm: OCM | None,
434
+ awsapi: AWSApi,
435
+ account_filter: str | None,
436
+ ) -> list[dict[str, Any]]:
363
437
  desired_state = []
364
438
 
365
439
  peering_info = cluster_info["peering"]
@@ -369,7 +443,7 @@ def build_desired_state_vpc_single_cluster(
369
443
  for peer_connection in peer_connections:
370
444
  # We only care about account-vpc peering providers
371
445
  peer_connection_provider = peer_connection["provider"]
372
- if not peer_connection_provider == "account-vpc":
446
+ if peer_connection_provider != "account-vpc":
373
447
  continue
374
448
  # requester is the cluster's AWS account
375
449
  requester = {
@@ -394,6 +468,7 @@ def build_desired_state_vpc_single_cluster(
394
468
  account, peer_vpc["vpc_id"], peer_vpc["region"]
395
469
  )
396
470
 
471
+ cluster_account = account
397
472
  # assume_role is the role to assume to provision the peering
398
473
  # connection request, through the accepter AWS account.
399
474
  provided_assume_role = peer_connection.get("assumeRole")
@@ -401,14 +476,16 @@ def build_desired_state_vpc_single_cluster(
401
476
  # to get the information from OCM. it likely means that
402
477
  # there is no OCM at all.
403
478
  if provided_assume_role:
404
- account["assume_role"] = provided_assume_role
479
+ cluster_account["assume_role"] = provided_assume_role
480
+ elif cluster_info["spec"].get("account"):
481
+ cluster_account = cluster_info["spec"].get("account")
405
482
  elif ocm is not None:
406
- account[
407
- "assume_role"
408
- ] = ocm.get_aws_infrastructure_access_terraform_assume_role(
409
- cluster,
410
- peer_vpc["account"]["uid"],
411
- peer_vpc["account"]["terraformUsername"],
483
+ cluster_account["assume_role"] = (
484
+ ocm.get_aws_infrastructure_access_terraform_assume_role(
485
+ cluster,
486
+ peer_vpc["account"]["uid"],
487
+ peer_vpc["account"]["terraformUsername"],
488
+ )
412
489
  )
413
490
  else:
414
491
  raise KeyError(
@@ -417,22 +494,32 @@ def build_desired_state_vpc_single_cluster(
417
494
  "or ocm should be defined to obtain role to assume"
418
495
  )
419
496
  account["assume_region"] = requester["region"]
420
- account["assume_cidr"] = requester["cidr_block"]
421
- requester_vpc_id, requester_route_table_ids, _ = awsapi.get_cluster_vpc_details(
422
- account, route_tables=peer_connection.get("manageRoutes")
497
+ cluster_account["assume_region"] = requester["region"]
498
+ cluster_account["assume_cidr"] = requester["cidr_block"]
499
+ requester_vpc_id, requester_route_table_ids, _, api_security_group_id = (
500
+ awsapi.get_cluster_vpc_details(
501
+ cluster_account,
502
+ route_tables=peer_connection.get("manageRoutes"),
503
+ hcp_vpc_endpoint_sg=_private_hosted_control_plane(cluster_info),
504
+ )
423
505
  )
424
506
 
425
507
  if requester_vpc_id is None:
426
- raise BadTerraformPeeringState(
427
- f"[{cluster}] could not find VPC ID for cluster"
508
+ logging.warning(
509
+ f"[{cluster}] could not find VPC ID for cluster. "
510
+ f"Skipping {peer_connection_provider} connection {peer_connection['name']}"
428
511
  )
512
+ continue
513
+
429
514
  requester["vpc_id"] = requester_vpc_id
430
515
  requester["route_table_ids"] = requester_route_table_ids
431
- requester["account"] = account
516
+ requester["account"] = cluster_account
517
+ requester["api_security_group_id"] = api_security_group_id
432
518
  accepter["account"] = account
433
519
  item = {
434
520
  "connection_provider": peer_connection_provider,
435
521
  "connection_name": connection_name,
522
+ "infra_account_name": account["name"],
436
523
  "requester": requester,
437
524
  "accepter": accepter,
438
525
  "deleted": peer_connection.get("delete", False),
@@ -441,9 +528,18 @@ def build_desired_state_vpc_single_cluster(
441
528
  return desired_state
442
529
 
443
530
 
531
+ def _private_hosted_control_plane(cluster_info: Mapping[str, Any]) -> bool:
532
+ return bool(
533
+ cluster_info["spec"].get("hypershift") and cluster_info["spec"].get("private")
534
+ )
535
+
536
+
444
537
  def build_desired_state_vpc(
445
- clusters, ocm_map: Optional[OCMMap], awsapi: AWSApi, account_filter: Optional[str]
446
- ):
538
+ clusters: Iterable[Mapping[str, Any]],
539
+ ocm_map: OCMMap | None,
540
+ awsapi: AWSApi,
541
+ account_filter: str | None,
542
+ ) -> tuple[list[dict[str, Any]], bool]:
447
543
  """
448
544
  Fetch state for VPC peerings between a cluster and a VPC (account)
449
545
  """
@@ -467,13 +563,16 @@ def build_desired_state_vpc(
467
563
 
468
564
  @defer
469
565
  def run(
470
- dry_run,
471
- print_to_file=None,
472
- enable_deletion=False,
473
- thread_pool_size=10,
474
- account_name: Optional[str] = None,
475
- defer=None,
476
- ):
566
+ dry_run: bool,
567
+ print_to_file: bool | None = None,
568
+ enable_deletion: bool = False,
569
+ thread_pool_size: int = 10,
570
+ account_name: str | None = None,
571
+ enable_extended_early_exit: bool = False,
572
+ extended_early_exit_cache_ttl_seconds: int = 3600,
573
+ log_cached_log_output: bool = False,
574
+ defer: Callable | None = None,
575
+ ) -> None:
477
576
  settings = queries.get_secret_reader_settings()
478
577
  clusters = queries.get_clusters_with_peering_settings()
479
578
  with_ocm = any(c.get("ocm") for c in clusters)
@@ -500,24 +599,18 @@ def run(
500
599
  errors.append(err)
501
600
 
502
601
  # Fetch desired state for cluster-to-account (vpc mesh) VPCs
503
- if ocm_map is not None:
504
- desired_state_vpc_mesh, err = build_desired_state_vpc_mesh(
505
- clusters, ocm_map, awsapi, account_name
506
- )
507
- desired_state.extend(desired_state_vpc_mesh)
508
- errors.append(err)
509
- else:
510
- logging.debug("account-vpc-mesh is not yet supported without OCM")
602
+ desired_state_vpc_mesh, err = build_desired_state_vpc_mesh(
603
+ clusters, ocm_map, awsapi, account_name
604
+ )
605
+ desired_state.extend(desired_state_vpc_mesh)
606
+ errors.append(err)
511
607
 
512
608
  # Fetch desired state for cluster-to-cluster VPCs
513
- if ocm_map is not None:
514
- desired_state_cluster, err = build_desired_state_all_clusters(
515
- clusters, ocm_map, awsapi, account_name
516
- )
517
- desired_state.extend(desired_state_cluster)
518
- errors.append(err)
519
- else:
520
- logging.debug("cluster-vpc is not yet supported without OCM")
609
+ desired_state_cluster, err = build_desired_state_all_clusters(
610
+ clusters, ocm_map, awsapi, account_name
611
+ )
612
+ desired_state.extend(desired_state_cluster)
613
+ errors.append(err)
521
614
 
522
615
  # check there are no repeated vpc connection names
523
616
  connection_names = [c["connection_name"] for c in desired_state]
@@ -525,58 +618,133 @@ def run(
525
618
  logging.error("duplicate vpc connection names found")
526
619
  sys.exit(1)
527
620
 
528
- participating_accounts = [item["requester"]["account"] for item in desired_state]
529
- participating_accounts += [item["accepter"]["account"] for item in desired_state]
530
- participating_account_names = [a["name"] for a in participating_accounts]
531
- accounts = [a for a in accounts if a["name"] in participating_account_names]
621
+ # infra accounts are the accounts hosting the terraform state
622
+ # - for cluster to vpc or vpc-mesh peering, the infra account is the accepter (non-cluster) account
623
+ # - for cluster-to-cluster peerings, the infra account is the default awsInfrastructureManagementAccount from the accepter cluster
624
+ infra_account_names = {d["infra_account_name"] for d in desired_state}
625
+ infra_accounts = [a for a in accounts if a["name"] in infra_account_names]
626
+ if not infra_accounts:
627
+ logging.warning(
628
+ f"No participating AWS accounts found, consider disabling this integration, account name: {account_name}"
629
+ )
630
+ return
631
+
632
+ participating_accounts: dict[str, list[Any]] = {}
633
+ for infra_account_name in infra_account_names:
634
+ participating_accounts[infra_account_name] = []
635
+ participating_accounts[infra_account_name].extend([
636
+ item["requester"]["account"]
637
+ for item in desired_state
638
+ if item["infra_account_name"] == infra_account_name
639
+ and (
640
+ item["requester"]["account"]["name"] != infra_account_name
641
+ or item["requester"]["account"].get("assume_role")
642
+ )
643
+ ])
644
+ participating_accounts[infra_account_name].extend([
645
+ item["accepter"]["account"]
646
+ for item in desired_state
647
+ if item["infra_account_name"] == infra_account_name
648
+ and (
649
+ item["accepter"]["account"]["name"] != infra_account_name
650
+ or item["accepter"]["account"].get("assume_role")
651
+ )
652
+ ])
532
653
 
654
+ account_by_name = {a["name"]: a for a in accounts}
533
655
  with terrascript.TerrascriptClient(
534
- QONTRACT_INTEGRATION, "", thread_pool_size, accounts, settings=settings
656
+ QONTRACT_INTEGRATION, "", thread_pool_size, infra_accounts, settings=settings
535
657
  ) as ts:
536
- ts.populate_additional_providers(participating_accounts)
658
+ rosa_cluster_accounts = [
659
+ account_by_name[c["spec"]["account"]["name"]]
660
+ for c in clusters
661
+ if c.get("spec") and c["spec"].get("account")
662
+ ]
663
+ ts.populate_configs(rosa_cluster_accounts)
664
+
665
+ for infra_account_name, items in participating_accounts.items():
666
+ ts.populate_additional_providers(infra_account_name, items)
537
667
  ts.populate_vpc_peerings(desired_state)
538
668
  working_dirs = ts.dump(print_to_file=print_to_file)
669
+ terraform_configurations = ts.terraform_configurations()
539
670
 
540
671
  if print_to_file:
541
672
  sys.exit(0 if dry_run else int(any(errors)))
542
673
 
674
+ if any(errors):
675
+ sys.exit(1)
676
+
543
677
  tf = terraform.TerraformClient(
544
678
  QONTRACT_INTEGRATION,
545
679
  QONTRACT_INTEGRATION_VERSION,
546
680
  "",
547
- accounts,
681
+ infra_accounts,
548
682
  working_dirs,
549
683
  thread_pool_size,
550
684
  awsapi,
551
685
  )
686
+ if defer:
687
+ defer(tf.cleanup)
688
+
689
+ runner_params: RunnerParams = {
690
+ "tf": tf,
691
+ "dry_run": dry_run,
692
+ "enable_deletion": enable_deletion,
693
+ }
694
+
695
+ if enable_extended_early_exit and get_feature_toggle_state(
696
+ "terraform-vpc-peerings-extended-early-exit",
697
+ default=True,
698
+ ):
699
+ cache_source = CacheSource(terraform_configurations=terraform_configurations)
700
+ extended_early_exit_run(
701
+ integration=QONTRACT_INTEGRATION,
702
+ integration_version=QONTRACT_INTEGRATION_VERSION,
703
+ dry_run=dry_run,
704
+ cache_source=cache_source,
705
+ shard=account_name if account_name else "",
706
+ ttl_seconds=extended_early_exit_cache_ttl_seconds,
707
+ logger=logging.getLogger(),
708
+ runner=runner,
709
+ runner_params=runner_params,
710
+ log_cached_log_output=log_cached_log_output,
711
+ )
712
+ else:
713
+ runner(**runner_params)
552
714
 
553
- if any(errors):
554
- sys.exit(1)
555
715
 
556
- defer(tf.cleanup)
716
+ class CacheSource(TypedDict):
717
+ terraform_configurations: dict[str, str]
557
718
 
719
+
720
+ class RunnerParams(TypedDict):
721
+ tf: terraform.TerraformClient
722
+ dry_run: bool
723
+ enable_deletion: bool
724
+
725
+
726
+ def runner(
727
+ dry_run: bool,
728
+ tf: terraform.TerraformClient,
729
+ enable_deletion: bool = False,
730
+ ) -> ExtendedEarlyExitRunnerResult:
558
731
  disabled_deletions_detected, err = tf.plan(enable_deletion)
559
- errors.append(err)
560
732
  if disabled_deletions_detected:
561
- logging.error("Deletions detected when they are disabled")
562
- sys.exit(1)
733
+ raise RuntimeError("Terraform plan has disabled deletions detected")
734
+ if err:
735
+ raise RuntimeError("Terraform plan has errors")
563
736
 
564
737
  if dry_run:
565
- sys.exit(int(any(errors)))
566
- if any(errors):
567
- sys.exit(1)
738
+ return ExtendedEarlyExitRunnerResult(payload={}, applied_count=0)
739
+
740
+ if err := tf.apply():
741
+ raise RuntimeError("Terraform apply has errors")
568
742
 
569
- errors.append(tf.apply())
570
- sys.exit(int(any(errors)))
743
+ return ExtendedEarlyExitRunnerResult(payload={}, applied_count=tf.apply_count)
571
744
 
572
745
 
573
- def early_exit_desired_state(
574
- print_to_file=None,
575
- enable_deletion=False,
576
- thread_pool_size=10,
577
- account_name: Optional[str] = None,
578
- ) -> dict[str, Any]:
579
- if account_name:
746
+ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
747
+ if kwargs.get("account_name"):
580
748
  raise ValueError(
581
749
  "terraform-vpc-peerings early-exit check does not support sharding yet"
582
750
  )