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,9 +1,12 @@
1
1
  import logging
2
+ import os
2
3
  import re
3
4
  import time
4
5
  from collections.abc import (
5
6
  Iterable,
7
+ Iterator,
6
8
  Mapping,
9
+ Sequence,
7
10
  )
8
11
  from datetime import datetime
9
12
  from functools import lru_cache
@@ -12,12 +15,11 @@ from typing import (
12
15
  TYPE_CHECKING,
13
16
  Any,
14
17
  Literal,
15
- Optional,
16
- Union,
17
18
  )
18
19
 
19
20
  import botocore
20
21
  from boto3 import Session
22
+ from botocore.config import Config
21
23
  from pydantic import BaseModel
22
24
  from sretoolbox.utils import threaded
23
25
 
@@ -39,10 +41,12 @@ if TYPE_CHECKING:
39
41
  TagTypeDef,
40
42
  TransitGatewayTypeDef,
41
43
  TransitGatewayVpcAttachmentTypeDef,
44
+ VpcEndpointTypeDef,
42
45
  VpcTypeDef,
43
46
  )
44
47
  from mypy_boto3_iam import IAMClient
45
48
  from mypy_boto3_iam.type_defs import AccessKeyMetadataTypeDef
49
+ from mypy_boto3_organizations import OrganizationsClient
46
50
  from mypy_boto3_rds import RDSClient
47
51
  from mypy_boto3_rds.type_defs import (
48
52
  DBInstanceMessageTypeDef,
@@ -54,40 +58,19 @@ if TYPE_CHECKING:
54
58
  ResourceRecordSetTypeDef,
55
59
  ResourceRecordTypeDef,
56
60
  )
61
+ from mypy_boto3_s3 import S3Client
57
62
  else:
58
- EC2Client = (
59
- EC2ServiceResource
60
- ) = (
61
- RouteTableTypeDef
62
- ) = (
63
- SubnetTypeDef
64
- ) = (
63
+ EC2Client = EC2ServiceResource = RouteTableTypeDef = SubnetTypeDef = (
65
64
  TransitGatewayTypeDef
66
- ) = (
67
- TransitGatewayVpcAttachmentTypeDef
68
- ) = (
69
- VpcTypeDef
70
- ) = (
71
- IAMClient
72
- ) = (
65
+ ) = TransitGatewayVpcAttachmentTypeDef = VpcTypeDef = IAMClient = (
73
66
  AccessKeyMetadataTypeDef
74
- ) = (
75
- ImageTypeDef
76
- ) = (
77
- TagTypeDef
78
- ) = (
79
- LaunchPermissionModificationsTypeDef
80
- ) = (
67
+ ) = ImageTypeDef = TagTypeDef = LaunchPermissionModificationsTypeDef = (
81
68
  FilterTypeDef
82
- ) = (
83
- Route53Client
84
- ) = (
85
- ResourceRecordSetTypeDef
86
- ) = (
87
- ResourceRecordTypeDef
88
- ) = (
69
+ ) = Route53Client = ResourceRecordSetTypeDef = ResourceRecordTypeDef = (
89
70
  HostedZoneTypeDef
90
- ) = RDSClient = DBInstanceMessageTypeDef = UpgradeTargetTypeDef = object
71
+ ) = RDSClient = DBInstanceMessageTypeDef = UpgradeTargetTypeDef = (
72
+ OrganizationsClient
73
+ ) = S3Client = object
91
74
 
92
75
 
93
76
  class InvalidResourceTypeError(Exception):
@@ -98,7 +81,7 @@ class MissingARNError(Exception):
98
81
  pass
99
82
 
100
83
 
101
- KeyStatus = Union[Literal["Active"], Literal["Inactive"]]
84
+ KeyStatus = Literal["Active"] | Literal["Inactive"]
102
85
 
103
86
  GOVCLOUD_PARTITION = "aws-us-gov"
104
87
 
@@ -153,6 +136,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
153
136
  self.get_vpc_default_sg_id = lru_cache()(self.get_vpc_default_sg_id)
154
137
  self.get_vpc_route_tables = lru_cache()(self.get_vpc_route_tables)
155
138
  self.get_vpc_subnets = lru_cache()(self.get_vpc_subnets)
139
+ self._get_vpc_endpoints = lru_cache()(self._get_vpc_endpoints)
156
140
 
157
141
  def init_sessions_and_resources(self, accounts: Iterable[awsh.Account]):
158
142
  results = threaded.run(
@@ -168,6 +152,13 @@ class AWSApi: # pylint: disable=too-many-public-methods
168
152
  access_key = secret["aws_access_key_id"]
169
153
  secret_key = secret["aws_secret_access_key"]
170
154
  region_name = account["resourcesDefaultRegion"]
155
+ self.use_fips = False
156
+
157
+ # ensure that govcloud accounts use FIPs endpoints
158
+ if "partition" in account and account["partition"] == GOVCLOUD_PARTITION:
159
+ logging.debug(f"FIPS endpoint enabled for AWS account: {account_name}")
160
+ self.use_fips = True
161
+
171
162
  session = Session(
172
163
  aws_access_key_id=access_key,
173
164
  aws_secret_access_key=secret_key,
@@ -198,45 +189,67 @@ class AWSApi: # pylint: disable=too-many-public-methods
198
189
  self,
199
190
  session: Session,
200
191
  service_name,
201
- region_name: Optional[str] = None,
192
+ region_name: str | None = None,
202
193
  ):
203
194
  region = region_name if region_name else session.region_name
204
- client = session.client(service_name, region_name=region)
195
+ client = session.client(
196
+ service_name,
197
+ region_name=region,
198
+ config=Config(use_fips_endpoint=self.use_fips),
199
+ )
205
200
  self._session_clients.append(client)
206
201
  return client
207
202
 
208
203
  @staticmethod
209
204
  # pylint: disable=method-hidden
210
205
  def _get_session_resource(
211
- session: Session, service_name, region_name: Optional[str] = None
206
+ session: Session, service_name, region_name: str | None = None
212
207
  ):
213
208
  region = region_name if region_name else session.region_name
214
209
  return session.resource(service_name, region_name=region)
215
210
 
216
211
  def _account_ec2_client(
217
- self, account_name: str, region_name: Optional[str] = None
212
+ self, account_name: str, region_name: str | None = None
218
213
  ) -> EC2Client:
219
214
  session = self.get_session(account_name)
220
215
  return self.get_session_client(session, "ec2", region_name)
221
216
 
222
217
  def _account_ec2_resource(
223
- self, account_name: str, region_name: Optional[str] = None
218
+ self, account_name: str, region_name: str | None = None
224
219
  ) -> EC2ServiceResource:
225
220
  session = self.get_session(account_name)
226
221
  return self._get_session_resource(session, "ec2", region_name)
227
222
 
228
223
  def _account_route53_client(
229
- self, account_name: str, region_name: Optional[str] = None
224
+ self, account_name: str, region_name: str | None = None
230
225
  ) -> Route53Client:
231
226
  session = self.get_session(account_name)
232
227
  return self.get_session_client(session, "route53", region_name)
233
228
 
234
229
  def _account_rds_client(
235
- self, account_name: str, region_name: Optional[str] = None
230
+ self, account_name: str, region_name: str | None = None
236
231
  ) -> RDSClient:
237
232
  session = self.get_session(account_name)
238
233
  return self.get_session_client(session, "rds", region_name)
239
234
 
235
+ def _account_cloudwatch_client(
236
+ self, account_name: str, region_name: str | None = None
237
+ ):
238
+ session = self.get_session(account_name)
239
+ return self.get_session_client(session, "logs", region_name)
240
+
241
+ def _account_organizations_client(
242
+ self, account_name: str, region_name: str | None = None
243
+ ) -> OrganizationsClient:
244
+ session = self.get_session(account_name)
245
+ return self.get_session_client(session, "organizations", region_name)
246
+
247
+ def _account_s3_client(
248
+ self, account_name: str, region_name: str | None = None
249
+ ) -> S3Client:
250
+ session = self.get_session(account_name)
251
+ return self.get_session_client(session, "s3", region_name)
252
+
240
253
  def init_users(self):
241
254
  self.users = {}
242
255
  for account, s in self.sessions.items():
@@ -478,7 +491,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
478
491
 
479
492
  @staticmethod
480
493
  def resource_has_special_name(account, type, resource):
481
- skip_msg = "[{}] skipping {} ".format(account, type) + "({} related) {}"
494
+ skip_msg = f"[{account}] skipping {type} " + "({} related) {}"
482
495
 
483
496
  ignore_names = {
484
497
  "production": ["prod"],
@@ -495,7 +508,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
495
508
  return False
496
509
 
497
510
  def resource_has_special_tags(self, account, type, resource, tags):
498
- skip_msg = "[{}] skipping {} ".format(account, type) + "({}={}) {}"
511
+ skip_msg = f"[{account}] skipping {type} " + "({}={}) {}"
499
512
 
500
513
  ignore_tags = {
501
514
  "ENV": ["prod", "stage", "staging"],
@@ -601,8 +614,8 @@ class AWSApi: # pylint: disable=too-many-public-methods
601
614
  if managed_by_integration_tag[0] == "terraform_resources":
602
615
  return "service_account"
603
616
 
604
- huh = "unrecognized managed_by_integration tag: {}".format(
605
- managed_by_integration_tag[0]
617
+ huh = (
618
+ f"unrecognized managed_by_integration tag: {managed_by_integration_tag[0]}"
606
619
  )
607
620
  raise InvalidResourceTypeError(huh)
608
621
 
@@ -725,7 +738,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
725
738
 
726
739
  def get_user_key_status(self, iam: IAMClient, user: str, key: str) -> KeyStatus:
727
740
  key_list = self._get_user_key_list(iam, user)
728
- return [k["Status"] for k in key_list if k["AccessKeyId"] == key][0]
741
+ return next(k["Status"] for k in key_list if k["AccessKeyId"] == key)
729
742
 
730
743
  def get_support_cases(self):
731
744
  all_support_cases = {}
@@ -796,17 +809,20 @@ class AWSApi: # pylint: disable=too-many-public-methods
796
809
  self.auth_tokens = auth_tokens
797
810
 
798
811
  @staticmethod
799
- def _get_account_assume_data(account: awsh.Account) -> tuple[str, str, str]:
812
+ def _get_account_assume_data(
813
+ account: awsh.Account,
814
+ ) -> tuple[str, str | None, str]:
800
815
  """
801
816
  returns mandatory data to be able to assume a role with this account:
802
817
  (account_name, assume_role, assume_region)
818
+ assume_role may be None for ROSA (CCS) clusters where we own the account
803
819
  """
804
- required_keys = ["name", "assume_role", "assume_region"]
805
- ok = all(elem in account.keys() for elem in required_keys)
820
+ required_keys = ["name", "assume_region"]
821
+ ok = all(elem in account for elem in required_keys)
806
822
  if not ok:
807
823
  account_name = account.get("name")
808
- raise KeyError("[{}] account is missing required keys".format(account_name))
809
- return (account["name"], account["assume_role"], account["assume_region"])
824
+ raise KeyError(f"[{account_name}] account is missing required keys")
825
+ return (account["name"], account.get("assume_role"), account["assume_region"])
810
826
 
811
827
  @staticmethod
812
828
  # pylint: disable=method-hidden
@@ -843,9 +859,17 @@ class AWSApi: # pylint: disable=too-many-public-methods
843
859
  return assumed_session
844
860
 
845
861
  def _get_assumed_role_client(
846
- self, account_name: str, assume_role: str, assume_region: str, client_type="ec2"
862
+ self,
863
+ account_name: str,
864
+ assume_role: str | None,
865
+ assume_region: str,
866
+ client_type="ec2",
847
867
  ) -> EC2Client:
848
868
  session = self.get_session(account_name)
869
+ if not assume_role:
870
+ return self.get_session_client(
871
+ session, client_type, region_name=assume_region
872
+ )
849
873
  sts = self.get_session_client(session, "sts")
850
874
  assumed_session = self._get_assume_role_session(
851
875
  sts, account_name, assume_role, assume_region
@@ -867,7 +891,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
867
891
  # filters a list of aws resources according to tags
868
892
  @staticmethod
869
893
  def filter_on_tags(
870
- items: Iterable[Any], tags: Optional[Mapping[str, str]] = None
894
+ items: Iterable[Any], tags: Mapping[str, str] | None = None
871
895
  ) -> list[Any]:
872
896
  if tags is None:
873
897
  tags = {}
@@ -892,12 +916,15 @@ class AWSApi: # pylint: disable=too-many-public-methods
892
916
  subnets = ec2.describe_subnets(Filters=[{"Name": "vpc-id", "Values": [vpc_id]}])
893
917
  return subnets.get("Subnets", [])
894
918
 
895
- def get_cluster_vpc_details(self, account, route_tables=False, subnets=False):
919
+ def get_cluster_vpc_details(
920
+ self, account, route_tables=False, subnets=False, hcp_vpc_endpoint_sg=False
921
+ ):
896
922
  """
897
923
  Returns a cluster VPC details:
898
924
  - VPC ID
899
925
  - Route table IDs (optional)
900
926
  - Subnets list including Subnet ID and Subnet Availability zone
927
+ - VPC Endpoint default security group of the private API router (optional)
901
928
  :param account: a dictionary containing the following keys:
902
929
  - name - name of the AWS account
903
930
  - assume_role - role to assume to get access
@@ -917,6 +944,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
917
944
 
918
945
  route_table_ids = None
919
946
  subnets_id_az = None
947
+ api_security_group_id = None
920
948
  if vpc_id:
921
949
  if route_tables:
922
950
  vpc_route_tables = self.get_vpc_route_tables(vpc_id, assumed_ec2)
@@ -927,15 +955,55 @@ class AWSApi: # pylint: disable=too-many-public-methods
927
955
  {"id": s["SubnetId"], "az": s["AvailabilityZone"]}
928
956
  for s in vpc_subnets
929
957
  ]
958
+ if hcp_vpc_endpoint_sg:
959
+ api_security_group_id = self._get_api_security_group_id(
960
+ assumed_ec2, vpc_id
961
+ )
930
962
 
931
- return vpc_id, route_table_ids, subnets_id_az
963
+ return vpc_id, route_table_ids, subnets_id_az, api_security_group_id
932
964
 
933
- def get_cluster_nat_gateways_egress_ips(self, account):
965
+ def _get_api_security_group_id(self, assumed_ec2, vpc_id):
966
+ endpoints = AWSApi._get_vpc_endpoints(
967
+ [
968
+ {"Name": "vpc-id", "Values": [vpc_id]},
969
+ {
970
+ "Name": "tag:AWSEndpointService",
971
+ "Values": ["private-router"],
972
+ },
973
+ ],
974
+ assumed_ec2,
975
+ )
976
+ if not endpoints:
977
+ return None
978
+ if len(endpoints) > 1:
979
+ raise ValueError(
980
+ f"exactly one VPC endpoint for private API router in VPC {vpc_id} expected but {len(endpoints)} found"
981
+ )
982
+ endpoint = endpoints[0]
983
+ vpc_endpoint_id = endpoint["VpcEndpointId"]
984
+ # https://github.com/openshift/hypershift/blob/c855f68e84e78924ccc9c2132b75dc7e30c4e1d8/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go#L4243
985
+ # https://github.com/openshift/hypershift/blob/2569f3353ef5ac0858eace9ee77310c3cc38b8e0/control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go#L787
986
+ security_groups = [
987
+ sg
988
+ for sg in endpoint["Groups"]
989
+ if sg["GroupName"].endswith("-default-sg")
990
+ or sg["GroupName"].endswith("-vpce-private-router")
991
+ ]
992
+ if len(security_groups) != 1:
993
+ raise ValueError(
994
+ f"exactly one VPC endpoint default security group for private API router {vpc_endpoint_id} "
995
+ f"in VPC {vpc_id} expected but {len(security_groups)} found"
996
+ )
997
+ return security_groups[0]["GroupId"]
998
+
999
+ def get_cluster_nat_gateways_egress_ips(self, account: dict[str, Any], vpc_id: str):
934
1000
  assumed_role_data = self._get_account_assume_data(account)
935
1001
  assumed_ec2 = self._get_assumed_role_client(*assumed_role_data)
936
1002
  nat_gateways = assumed_ec2.describe_nat_gateways()
937
1003
  egress_ips = set()
938
- for nat in nat_gateways.get("NatGateways"):
1004
+ for nat in nat_gateways.get("NatGateways") or []:
1005
+ if nat["VpcId"] != vpc_id:
1006
+ continue
939
1007
  for address in nat["NatGatewayAddresses"]:
940
1008
  egress_ips.add(address["PublicIp"])
941
1009
 
@@ -994,7 +1062,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
994
1062
  account: Mapping[str, Any],
995
1063
  owner_account: Mapping[str, Any],
996
1064
  regex: str,
997
- region: Optional[str] = None,
1065
+ region: str | None = None,
998
1066
  ) -> list[dict[str, Any]]:
999
1067
  ec2 = self._account_ec2_client(account["name"], region_name=region)
1000
1068
  images = self.get_account_amis(ec2, owner=owner_account["uid"])
@@ -1005,7 +1073,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
1005
1073
  account: Mapping[str, Any],
1006
1074
  share_account_uid: str,
1007
1075
  image_id: str,
1008
- region: Optional[str] = None,
1076
+ region: str | None = None,
1009
1077
  ):
1010
1078
  ec2 = self._account_ec2_resource(account["name"], region)
1011
1079
  image = ec2.Image(image_id)
@@ -1014,6 +1082,67 @@ class AWSApi: # pylint: disable=too-many-public-methods
1014
1082
  }
1015
1083
  image.modify_attribute(LaunchPermission=launch_permission)
1016
1084
 
1085
+ @staticmethod
1086
+ def _normalize_log_group_arn(arn: str) -> str:
1087
+ # DescribeLogGroups response arn has additional :* at the end
1088
+ return arn.rstrip(":*")
1089
+
1090
+ def create_cloudwatch_tag(
1091
+ self,
1092
+ account_name: str,
1093
+ arn: str,
1094
+ new_tag: dict[str, str],
1095
+ region_name: str | None = None,
1096
+ ) -> None:
1097
+ client = self._account_cloudwatch_client(account_name, region_name=region_name)
1098
+ client.tag_resource(
1099
+ resourceArn=self._normalize_log_group_arn(arn),
1100
+ tags=new_tag,
1101
+ )
1102
+
1103
+ def get_cloudwatch_log_groups(
1104
+ self,
1105
+ account_name: str,
1106
+ region_name: str | None = None,
1107
+ ) -> Iterator[dict]:
1108
+ client = self._account_cloudwatch_client(account_name, region_name=region_name)
1109
+ paginator = client.get_paginator("describe_log_groups")
1110
+ for page in paginator.paginate():
1111
+ yield from page["logGroups"]
1112
+
1113
+ def get_cloudwatch_log_group_tags(
1114
+ self,
1115
+ account_name: str,
1116
+ arn: str,
1117
+ region_name: str | None = None,
1118
+ ) -> dict[str, str]:
1119
+ client = self._account_cloudwatch_client(account_name, region_name=region_name)
1120
+ tags = client.list_tags_for_resource(
1121
+ resourceArn=self._normalize_log_group_arn(arn),
1122
+ )
1123
+ return tags.get("tags", {})
1124
+
1125
+ def set_cloudwatch_log_retention(
1126
+ self,
1127
+ account_name: str,
1128
+ group_name: str,
1129
+ retention_days: int,
1130
+ region_name: str | None = None,
1131
+ ):
1132
+ client = self._account_cloudwatch_client(account_name, region_name=region_name)
1133
+ client.put_retention_policy(
1134
+ logGroupName=group_name, retentionInDays=retention_days
1135
+ )
1136
+
1137
+ def delete_cloudwatch_log_group(
1138
+ self,
1139
+ account_name: str,
1140
+ group_name: str,
1141
+ region_name: str | None = None,
1142
+ ):
1143
+ client = self._account_cloudwatch_client(account_name, region_name=region_name)
1144
+ client.delete_log_group(logGroupName=group_name)
1145
+
1017
1146
  def create_tag(
1018
1147
  self, account: Mapping[str, Any], resource_id: str, tag: Mapping[str, str]
1019
1148
  ):
@@ -1053,7 +1182,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
1053
1182
 
1054
1183
  @staticmethod
1055
1184
  # pylint: disable=method-hidden
1056
- def get_vpc_default_sg_id(vpc_id: str, ec2: EC2Client) -> Optional[str]:
1185
+ def get_vpc_default_sg_id(vpc_id: str, ec2: EC2Client) -> str | None:
1057
1186
  vpc_security_groups = ec2.describe_security_groups(
1058
1187
  Filters=[
1059
1188
  {"Name": "vpc-id", "Values": [vpc_id]},
@@ -1074,7 +1203,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
1074
1203
 
1075
1204
  def get_tgw_default_route_table_id(
1076
1205
  self, ec2: EC2Client, tgw_id: str, tags: Mapping[str, str]
1077
- ) -> Optional[str]:
1206
+ ) -> str | None:
1078
1207
  tgws = self.get_transit_gateways(ec2)
1079
1208
  tgws = self.filter_on_tags(tgws, tags)
1080
1209
  # we know the party TGW exists, so we can be
@@ -1245,6 +1374,14 @@ class AWSApi: # pylint: disable=too-many-public-methods
1245
1374
 
1246
1375
  return results
1247
1376
 
1377
+ @staticmethod
1378
+ # pylint: disable=method-hidden
1379
+ def _get_vpc_endpoints(
1380
+ filters: Sequence[FilterTypeDef], ec2: EC2Client
1381
+ ) -> list["VpcEndpointTypeDef"]:
1382
+ atts = ec2.describe_vpc_endpoints(Filters=filters)
1383
+ return atts.get("VpcEndpoints", [])
1384
+
1248
1385
  @staticmethod
1249
1386
  def _get_hosted_zone_id(zone: HostedZoneTypeDef) -> str:
1250
1387
  # 'Id': '/hostedzone/THISISTHEZONEID'
@@ -1257,7 +1394,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
1257
1394
  if not zones:
1258
1395
  return []
1259
1396
  zone_id = self._get_hosted_zone_id(zones[0])
1260
- return route53.list_resource_record_sets(HostedZoneId=zone_id)[
1397
+ return route53.list_resource_record_sets(HostedZoneId=zone_id)[ # type: ignore[return-value]
1261
1398
  "ResourceRecordSets"
1262
1399
  ]
1263
1400
 
@@ -1425,7 +1562,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
1425
1562
 
1426
1563
  def get_image_id(
1427
1564
  self, account_name: str, region_name: str, tags: Iterable[AmiTag]
1428
- ) -> Optional[str]:
1565
+ ) -> str | None:
1429
1566
  """
1430
1567
  Get AMI ID matching the specified criteria.
1431
1568
 
@@ -1454,7 +1591,7 @@ class AWSApi: # pylint: disable=too-many-public-methods
1454
1591
  self,
1455
1592
  account_name: str,
1456
1593
  db_instance_name: str,
1457
- region_name: Optional[str] = None,
1594
+ region_name: str | None = None,
1458
1595
  ) -> DBInstanceMessageTypeDef:
1459
1596
  """
1460
1597
  Describe a single RDS instance.
@@ -1471,12 +1608,20 @@ class AWSApi: # pylint: disable=too-many-public-methods
1471
1608
  rds = self._account_rds_client(account_name, **optional_kwargs)
1472
1609
  return rds.describe_db_instances(DBInstanceIdentifier=db_instance_name)
1473
1610
 
1611
+ def describe_rds_recommendations(
1612
+ self,
1613
+ account_name: str,
1614
+ region_name: str | None = None,
1615
+ ):
1616
+ rds = self._account_rds_client(account_name, region_name)
1617
+ return rds.describe_db_recommendations()
1618
+
1474
1619
  def get_db_valid_upgrade_target(
1475
1620
  self,
1476
1621
  account_name: str,
1477
1622
  engine: str,
1478
1623
  engine_version: str,
1479
- region_name: Optional[str] = None,
1624
+ region_name: str | None = None,
1480
1625
  ) -> list[UpgradeTargetTypeDef]:
1481
1626
  """
1482
1627
  Get a list version of the database engine that a DB instance can be upgraded to.
@@ -1493,6 +1638,74 @@ class AWSApi: # pylint: disable=too-many-public-methods
1493
1638
  optional_kwargs["region_name"] = region_name
1494
1639
 
1495
1640
  rds = self._account_rds_client(account_name, **optional_kwargs)
1496
- return rds.describe_db_engine_versions(
1497
- Engine=engine, EngineVersion=engine_version
1498
- )["DBEngineVersions"][0]["ValidUpgradeTarget"]
1641
+ response = rds.describe_db_engine_versions(
1642
+ Engine=engine,
1643
+ EngineVersion=engine_version,
1644
+ IncludeAll=True,
1645
+ )
1646
+
1647
+ if versions := response["DBEngineVersions"]:
1648
+ return versions[0]["ValidUpgradeTarget"]
1649
+ return []
1650
+
1651
+ def describe_db_parameter_group(
1652
+ self,
1653
+ account_name: str,
1654
+ db_parameter_group_name: str,
1655
+ region_name: str | None = None,
1656
+ ) -> dict[str, str]:
1657
+ optional_kwargs = {}
1658
+
1659
+ if region_name:
1660
+ optional_kwargs["region_name"] = region_name
1661
+
1662
+ rds = self._account_rds_client(account_name, **optional_kwargs)
1663
+ paginator = rds.get_paginator("describe_db_parameters")
1664
+ parameters = {}
1665
+ for page in paginator.paginate(DBParameterGroupName=db_parameter_group_name):
1666
+ for param in page.get("Parameters", []):
1667
+ parameters[param["ParameterName"]] = param.get("ParameterValue", "")
1668
+ return parameters
1669
+
1670
+ def get_organization_billing_account(self, account_name: str) -> str:
1671
+ org = self._account_organizations_client(account_name)
1672
+ return org.describe_organization()["Organization"]["MasterAccountId"]
1673
+
1674
+ def get_s3_object_content(
1675
+ self,
1676
+ account_name: str,
1677
+ bucket_name: str,
1678
+ path: str,
1679
+ region_name: str | None = None,
1680
+ ) -> str:
1681
+ s3 = self._account_s3_client(account_name, region_name=region_name)
1682
+ return (
1683
+ s3.get_object(Bucket=bucket_name, Key=path)["Body"].read().decode("utf-8")
1684
+ )
1685
+
1686
+ def list_s3_objects(
1687
+ self,
1688
+ account_name: str,
1689
+ bucket_name: str,
1690
+ path: str,
1691
+ region_name: str | None = None,
1692
+ ) -> list[str]:
1693
+ s3 = self._account_s3_client(account_name, region_name=region_name)
1694
+ objects = s3.list_objects_v2(Bucket=bucket_name, Prefix=path, Delimiter="/")[
1695
+ "Contents"
1696
+ ]
1697
+ return [
1698
+ obj["Key"]
1699
+ for obj in sorted(
1700
+ objects, key=lambda obj: obj["LastModified"], reverse=True
1701
+ )
1702
+ ]
1703
+
1704
+
1705
+ def aws_config_file_path() -> str | None:
1706
+ config_file_path = os.path.expanduser(
1707
+ os.environ.get("AWS_CONFIG_FILE", "~/.aws/config")
1708
+ )
1709
+ if not os.path.isfile(config_file_path):
1710
+ return None
1711
+ return config_file_path
File without changes
@@ -0,0 +1,23 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ if TYPE_CHECKING:
4
+ from mypy_boto3_account import AccountClient
5
+ else:
6
+ AccountClient = object
7
+
8
+
9
+ class AWSApiAccount:
10
+ def __init__(self, client: AccountClient) -> None:
11
+ self.client = client
12
+
13
+ def set_security_contact(
14
+ self, name: str, title: str, email: str, phone_number: str
15
+ ) -> None:
16
+ """Set the security contact for the account."""
17
+ self.client.put_alternate_contact(
18
+ AlternateContactType="SECURITY",
19
+ EmailAddress=email,
20
+ Name=name,
21
+ Title=title,
22
+ PhoneNumber=phone_number,
23
+ )