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
reconcile/ocm_clusters.py CHANGED
@@ -12,12 +12,32 @@ from reconcile import (
12
12
  mr_client_gateway,
13
13
  queries,
14
14
  )
15
- from reconcile.ocm.types import OCMSpec
15
+ from reconcile.ocm.types import (
16
+ OCMSpec,
17
+ ROSAClusterAWSAccount,
18
+ ROSAClusterSpec,
19
+ ROSAOcmAwsAttrs,
20
+ ROSAOcmAwsStsAttrs,
21
+ )
16
22
  from reconcile.status import ExitCodes
17
23
  from reconcile.utils.disabled_integrations import integration_is_enabled
18
- from reconcile.utils.semver_helper import parse_semver
24
+ from reconcile.utils.jobcontroller.controller import build_job_controller
25
+ from reconcile.utils.ocm.products import (
26
+ IGNORE_NETWORK_TYPE_ATTR,
27
+ OCMProduct,
28
+ OCMProductPortfolio,
29
+ OCMValidationException,
30
+ build_product_portfolio,
31
+ )
32
+ from reconcile.utils.rosa.session import RosaSessionBuilder
33
+ from reconcile.utils.runtime.integration import (
34
+ PydanticRunParams,
35
+ QontractReconcileIntegration,
36
+ )
37
+ from reconcile.utils.semver_helper import make_semver, parse_semver
19
38
 
20
39
  QONTRACT_INTEGRATION = "ocm-clusters"
40
+ QONTRACT_INTEGRATION_VERSION = make_semver(0, 1, 0)
21
41
 
22
42
 
23
43
  def _set_rosa_ocm_attrs(cluster: Mapping[str, Any]):
@@ -26,30 +46,44 @@ def _set_rosa_ocm_attrs(cluster: Mapping[str, Any]):
26
46
  but the cluster only needs the target OCM environment where it belongs.
27
47
  This method changes the cluster dictionary to include just those.
28
48
  """
29
-
30
- rosa = cluster["spec"]["account"]["rosa"]
31
- ocm_env = [
32
- env
33
- for env in rosa["ocm_environments"]
34
- if env["ocm"]["name"] == cluster["ocm"]["name"]
35
- ]
36
-
37
- if len(ocm_env) != 1:
38
- logging.error(
39
- "The cluster's OCM reference does not exist or it is duplicated in the AWS account manifest. "
40
- "Check the cluster's AWS account rosa configuration. "
41
- f"OCM:{cluster['ocm']['name']}, AWSAcc:{cluster['spec']['account']['uid']}"
49
+ account = cluster["spec"]["account"]
50
+ uid = account["uid"]
51
+ rosa_ocm_configs = account["rosa"]
52
+ rosa: ROSAOcmAwsAttrs | None = None
53
+ if rosa_ocm_configs:
54
+ ocm_env = [
55
+ env
56
+ for env in rosa_ocm_configs["ocm_environments"]
57
+ if env["ocm"]["name"] == cluster["ocm"]["name"]
58
+ ]
59
+ if len(ocm_env) != 1:
60
+ logging.error(
61
+ "The cluster's OCM reference does not exist or it is duplicated in the AWS account manifest. "
62
+ "Check the cluster's AWS account rosa configuration. "
63
+ f"OCM:{cluster['ocm']['name']}, AWSAcc:{cluster['spec']['account']['uid']}"
64
+ )
65
+ sys.exit(ExitCodes.ERROR)
66
+ env = ocm_env[0]
67
+ rosa = ROSAOcmAwsAttrs(
68
+ creator_role_arn=env["creator_role_arn"],
69
+ sts=ROSAOcmAwsStsAttrs(
70
+ installer_role_arn=env["installer_role_arn"],
71
+ support_role_arn=env["support_role_arn"],
72
+ controlplane_role_arn=env.get("controlplane_role_arn"),
73
+ worker_role_arn=env["worker_role_arn"],
74
+ ),
42
75
  )
43
- sys.exit(ExitCodes.ERROR)
44
-
45
- rosa["creator_role_arn"] = ocm_env[0]["creator_role_arn"]
46
- rosa["installer_role_arn"] = ocm_env[0]["installer_role_arn"]
47
- rosa["support_role_arn"] = ocm_env[0]["support_role_arn"]
48
- rosa["controlplane_role_arn"] = ocm_env[0]["controlplane_role_arn"]
49
- rosa["worker_role_arn"] = ocm_env[0]["worker_role_arn"]
76
+ else:
77
+ rosa = None
50
78
 
51
- # Make pydantic happy
52
- del rosa["ocm_environments"]
79
+ # doing this allows to exclude account fields which can be queried in graphql
80
+ rosa_cluster_aws_account = ROSAClusterAWSAccount(
81
+ uid=uid,
82
+ rosa=rosa,
83
+ )
84
+ if billing_account := account.get("billingAccount"):
85
+ rosa_cluster_aws_account.billing_account_id = billing_account["uid"]
86
+ cluster["spec"]["account"] = rosa_cluster_aws_account
53
87
 
54
88
 
55
89
  def fetch_desired_state(clusters: Iterable[Mapping[str, Any]]) -> dict[str, OCMSpec]:
@@ -91,10 +125,10 @@ def _cluster_version_needs_update(
91
125
  if not desired_version:
92
126
  return True
93
127
 
94
- desired_version = parse_semver(desired_version)
95
- current_version = parse_semver(current_version)
128
+ parsed_desired_version = parse_semver(desired_version)
129
+ parsed_current_version = parse_semver(current_version)
96
130
 
97
- if current_version > desired_version:
131
+ if parsed_current_version > parsed_desired_version:
98
132
  # current version is geater due to an upgrade.
99
133
  # submit MR to update cluster version
100
134
  logging.info(
@@ -104,7 +138,7 @@ def _cluster_version_needs_update(
104
138
  )
105
139
  return True
106
140
 
107
- if current_version < desired_version:
141
+ if parsed_current_version < parsed_desired_version:
108
142
  raise ClusterVersionError(
109
143
  f"[{cluster}] desired version [{desired_version}] is greater than "
110
144
  f"current version [{current_version}]. Please correct version to be "
@@ -152,17 +186,29 @@ def get_app_interface_spec_updates(
152
186
  desired_spec.spec.disable_user_workload_monitoring is None
153
187
  and current_spec.spec.disable_user_workload_monitoring
154
188
  ):
155
- ocm_spec_updates[
156
- ocmmod.SPEC_ATTR_DISABLE_UWM
157
- ] = current_spec.spec.disable_user_workload_monitoring
189
+ ocm_spec_updates[ocmmod.SPEC_ATTR_DISABLE_UWM] = (
190
+ current_spec.spec.disable_user_workload_monitoring
191
+ )
158
192
 
159
193
  if (
160
194
  current_spec.spec.provision_shard_id is not None
161
195
  and desired_spec.spec.provision_shard_id != current_spec.spec.provision_shard_id
162
196
  ):
163
- ocm_spec_updates[
164
- ocmmod.SPEC_ATTR_PROVISION_SHARD_ID
165
- ] = current_spec.spec.provision_shard_id
197
+ ocm_spec_updates[ocmmod.SPEC_ATTR_PROVISION_SHARD_ID] = (
198
+ current_spec.spec.provision_shard_id
199
+ )
200
+
201
+ if isinstance(current_spec.spec, ROSAClusterSpec) and isinstance(
202
+ desired_spec.spec, ROSAClusterSpec
203
+ ):
204
+ if (
205
+ current_spec.spec.oidc_endpoint_url
206
+ and desired_spec.spec.oidc_endpoint_url
207
+ != current_spec.spec.oidc_endpoint_url
208
+ ):
209
+ ocm_spec_updates[ocmmod.SPEC_ATTR_OIDC_ENDPONT_URL] = (
210
+ current_spec.spec.oidc_endpoint_url
211
+ )
166
212
 
167
213
  if current_spec.server_url and desired_spec.server_url != current_spec.server_url:
168
214
  root_updates[ocmmod.SPEC_ATTR_SERVER_URL] = current_spec.server_url
@@ -187,7 +233,7 @@ def get_app_interface_spec_updates(
187
233
 
188
234
 
189
235
  def get_cluster_ocm_update_spec(
190
- ocm: ocmmod.OCM, cluster: str, current_spec: OCMSpec, desired_spec: OCMSpec
236
+ product: OCMProduct, cluster: str, current_spec: OCMSpec, desired_spec: OCMSpec
191
237
  ) -> tuple[dict[str, Any], bool]:
192
238
  """Get cluster updates to request to OCM api
193
239
 
@@ -198,29 +244,31 @@ def get_cluster_ocm_update_spec(
198
244
  :return: a tuple with the updates to request to OCM and a bool to notify errors
199
245
  """
200
246
 
201
- impl = ocmmod.OCM_PRODUCTS_IMPL[current_spec.spec.product]
202
-
203
247
  error = False
204
248
  if not desired_spec.network.type:
205
249
  desired_spec.network.type = "OVNKubernetes"
206
250
 
207
251
  cspec = current_spec.spec.dict()
208
- cspec[ocmmod.SPEC_ATTR_NETWORK] = current_spec.network.dict()
252
+ cspec[ocmmod.SPEC_ATTR_NETWORK] = current_spec.network.dict(
253
+ exclude={IGNORE_NETWORK_TYPE_ATTR}
254
+ )
209
255
 
210
256
  dspec = desired_spec.spec.dict()
211
- dspec[ocmmod.SPEC_ATTR_NETWORK] = desired_spec.network.dict()
257
+ dspec[ocmmod.SPEC_ATTR_NETWORK] = desired_spec.network.dict(
258
+ exclude={IGNORE_NETWORK_TYPE_ATTR}
259
+ )
212
260
 
213
261
  # Convert ocm specs to dicts, removing null values and excluded attributes
214
262
  current_ocm_spec = {
215
263
  k: v
216
264
  for k, v in cspec.items()
217
- if v is not None and k not in impl.EXCLUDED_SPEC_FIELDS
265
+ if v is not None and k not in product.EXCLUDED_SPEC_FIELDS
218
266
  }
219
267
 
220
268
  desired_ocm_spec = {
221
269
  k: v
222
270
  for k, v in dspec.items()
223
- if v is not None and k not in impl.EXCLUDED_SPEC_FIELDS
271
+ if v is not None and k not in product.EXCLUDED_SPEC_FIELDS
224
272
  }
225
273
 
226
274
  # Updated attributes in app-interface
@@ -235,7 +283,7 @@ def get_cluster_ocm_update_spec(
235
283
 
236
284
  diffs = deleted_attrs | updated_attrs
237
285
 
238
- not_allowed_updates = set(diffs) - impl.ALLOWED_SPEC_UPDATE_FIELDS
286
+ not_allowed_updates = set(diffs) - product.ALLOWED_SPEC_UPDATE_FIELDS
239
287
  if not_allowed_updates:
240
288
  error = True
241
289
  logging.error(f"[{cluster}] invalid updates: {not_allowed_updates}")
@@ -244,7 +292,7 @@ def get_cluster_ocm_update_spec(
244
292
 
245
293
 
246
294
  def _app_interface_updates_mr(
247
- clusters_updates: Mapping[str, Any], gitlab_project_id: str, dry_run: bool
295
+ clusters_updates: Mapping[str, Any], gitlab_project_id: str | None, dry_run: bool
248
296
  ):
249
297
  """Creates an MR to app-interface with the necessary cluster manifest updates
250
298
 
@@ -278,94 +326,133 @@ def _cluster_is_compatible(cluster: Mapping[str, Any]) -> bool:
278
326
  return cluster.get("ocm") is not None
279
327
 
280
328
 
281
- def run(dry_run: bool, gitlab_project_id=None, thread_pool_size=10):
282
- settings = queries.get_app_interface_settings()
283
- clusters = queries.get_clusters()
284
- clusters = [
285
- c
286
- for c in clusters
287
- if integration_is_enabled(QONTRACT_INTEGRATION, c) and _cluster_is_compatible(c)
288
- ]
289
- if not clusters:
290
- logging.debug("No OCM cluster definitions found in app-interface")
291
- sys.exit(ExitCodes.SUCCESS)
292
-
293
- ocm_map = ocmmod.OCMMap(
294
- clusters=clusters,
295
- integration=QONTRACT_INTEGRATION,
296
- settings=settings,
297
- init_provision_shards=True,
298
- )
329
+ class OcmClustersParams(PydanticRunParams):
330
+ gitlab_project_id: str | None = None
331
+ thread_pool_size: int = 10
299
332
 
300
- # current_state is the state got from the ocm api
301
- current_state, pending_state = ocm_map.cluster_specs()
302
- desired_state = fetch_desired_state(clusters)
333
+ # rosa job controller params
334
+ job_controller_cluster: str | None = None
335
+ job_controller_namespace: str | None = None
336
+ rosa_job_service_account: str | None = None
337
+ rosa_role: str | None = None
338
+ rosa_job_image: str | None = None
303
339
 
304
- error = False
305
- clusters_updates = {}
306
-
307
- for cluster_name, desired_spec in desired_state.items():
308
- current_spec = current_state.get(cluster_name)
309
- if current_spec:
310
- # App-Interface manifests updates.
311
- # OCM populated attributes that are not set in app-interface.
312
- # These updates are performed with a single MR out of this main loop
313
- clusters_updates[cluster_name], err = get_app_interface_spec_updates(
314
- cluster_name, current_spec, desired_spec
315
- )
316
- if err:
317
- error = True
318
-
319
- # OCM API Updates
320
- # Changes made to app-interface manifests that need to be requested
321
- # to the OCM Api
322
- ocm = ocm_map.get(cluster_name)
323
- update_spec, err = get_cluster_ocm_update_spec(
324
- ocm, cluster_name, current_spec, desired_spec
325
- )
326
- if err:
327
- error = True
328
- continue
329
-
330
- # update cluster
331
- # TODO(mafriedm): check dry_run in OCM API patch
332
- if update_spec:
333
- logging.info(["update_cluster", cluster_name])
334
- logging.debug(
335
- f"current_spec: {current_spec}, desired_spec: {desired_spec}"
340
+
341
+ class OcmClusters(QontractReconcileIntegration[OcmClustersParams]):
342
+ @property
343
+ def name(self) -> str:
344
+ return QONTRACT_INTEGRATION
345
+
346
+ def rosa_session_builder(self) -> RosaSessionBuilder | None:
347
+ if (
348
+ self.params.job_controller_cluster is None
349
+ or self.params.job_controller_namespace is None
350
+ or self.params.rosa_job_service_account is None
351
+ or self.params.rosa_role is None
352
+ or self.params.rosa_job_image is None
353
+ ):
354
+ return None
355
+ return RosaSessionBuilder(
356
+ aws_iam_role=self.params.rosa_role,
357
+ image=self.params.rosa_job_image,
358
+ service_account=self.params.rosa_job_service_account,
359
+ job_controller=build_job_controller(
360
+ cluster=self.params.job_controller_cluster,
361
+ namespace=self.params.job_controller_namespace,
362
+ integration=self.name,
363
+ integration_version=QONTRACT_INTEGRATION_VERSION,
364
+ secret_reader=self.secret_reader,
365
+ dry_run=False,
366
+ ),
367
+ )
368
+
369
+ def assemble_product_portfolio(self) -> OCMProductPortfolio:
370
+ return build_product_portfolio(self.rosa_session_builder())
371
+
372
+ def run(self, dry_run: bool) -> None:
373
+ settings = queries.get_app_interface_settings()
374
+ clusters = queries.get_clusters()
375
+ clusters = [
376
+ c
377
+ for c in clusters
378
+ if integration_is_enabled(self.name, c) and _cluster_is_compatible(c)
379
+ ]
380
+ if not clusters:
381
+ logging.debug("No OCM cluster definitions found in app-interface")
382
+ sys.exit(ExitCodes.SUCCESS)
383
+
384
+ product_portfolio = self.assemble_product_portfolio()
385
+ ocm_map = ocmmod.OCMMap(
386
+ clusters=clusters,
387
+ integration=self.name,
388
+ settings=settings,
389
+ init_provision_shards=True,
390
+ product_portfolio=product_portfolio,
391
+ )
392
+
393
+ # current_state is the state got from the ocm api
394
+ current_state, pending_state = ocm_map.cluster_specs()
395
+ desired_state = fetch_desired_state(clusters)
396
+
397
+ error = False
398
+ clusters_updates = {}
399
+
400
+ for cluster_name, desired_spec in desired_state.items():
401
+ current_spec = current_state.get(cluster_name)
402
+ if current_spec:
403
+ # App-Interface manifests updates.
404
+ # OCM populated attributes that are not set in app-interface.
405
+ # These updates are performed with a single MR out of this main loop
406
+ clusters_updates[cluster_name], err = get_app_interface_spec_updates(
407
+ cluster_name, current_spec, desired_spec
336
408
  )
337
- if not dry_run:
338
- ocm = ocm_map.get(cluster_name)
339
- try:
340
- ocm.update_cluster(cluster_name, update_spec, dry_run)
341
- except NotImplementedError:
342
- logging.error(
343
- f"[{cluster_name}] Update clusters is currently not "
344
- f"implemented for [{desired_spec.spec.product}] product. "
345
- "Fix the app-interface manifest with the required changes. "
346
- f" {update_spec}"
347
- )
348
- # Not marking error because in cases where specific product
349
- # updates are not yet supported, changes made directly in OCM
350
- # and not added to app-interface would trigger this exception
351
- # and break this integration
352
- # error = True
353
- else:
354
- # create cluster
355
- if cluster_name in pending_state:
356
- continue
357
- logging.info(["create_cluster", cluster_name])
358
- ocm = ocm_map.get(cluster_name)
359
- try:
360
- ocm.create_cluster(cluster_name, desired_spec, dry_run)
361
- except NotImplementedError:
362
- logging.error(
363
- f"[{cluster_name}] Create clusters is not currently implemented "
364
- f"for [{desired_spec.spec.product}] product type. Make sure the "
365
- "cluster exists and it is returned by the OCM api before adding "
366
- "its manifest to app-interface"
409
+ if err:
410
+ error = True
411
+
412
+ # OCM API Updates
413
+ # Changes made to app-interface manifests that need to be requested
414
+ # to the OCM Api
415
+ ocm = ocm_map.get(cluster_name)
416
+ product = product_portfolio.get_product_impl(
417
+ current_spec.spec.product, current_spec.spec.hypershift
367
418
  )
368
- error = True
369
-
370
- _app_interface_updates_mr(clusters_updates, gitlab_project_id, dry_run)
371
- sys.exit(int(error))
419
+ update_spec, err = get_cluster_ocm_update_spec(
420
+ product, cluster_name, current_spec, desired_spec
421
+ )
422
+ if err:
423
+ error = True
424
+ continue
425
+
426
+ # update cluster
427
+ if update_spec:
428
+ logging.info(["update_cluster", cluster_name])
429
+ logging.debug(
430
+ f"current_spec: {current_spec}, desired_spec: {desired_spec}"
431
+ )
432
+ ocm = ocm_map.get(cluster_name)
433
+ ocm.update_cluster(cluster_name, update_spec, dry_run)
434
+
435
+ else:
436
+ # create cluster
437
+ if cluster_name in pending_state:
438
+ continue
439
+ logging.info(["create_cluster", cluster_name])
440
+ ocm = ocm_map.get(cluster_name)
441
+ try:
442
+ ocm.create_cluster(cluster_name, desired_spec, dry_run)
443
+ except NotImplementedError:
444
+ logging.error(
445
+ f"[{cluster_name}] Create clusters is not currently implemented "
446
+ f"for [{desired_spec.spec.product}] product type. Make sure the "
447
+ "cluster exists and it is returned by the OCM api before adding "
448
+ "its manifest to app-interface"
449
+ )
450
+ error = True
451
+ except OCMValidationException as e:
452
+ logging.error("[%s] Error creating cluster: %s", cluster_name, e)
453
+ error = True
454
+
455
+ _app_interface_updates_mr(
456
+ clusters_updates, self.params.gitlab_project_id, dry_run
457
+ )
458
+ sys.exit(int(error))
@@ -12,6 +12,13 @@ from reconcile.utils.ocm import OCMMap
12
12
  QONTRACT_INTEGRATION = "ocm-external-configuration-labels"
13
13
 
14
14
 
15
+ def get_allowed_labels_for_cluster(cluster: dict[str, Any]) -> set[str]:
16
+ allowed_labels = cluster.get("ocm", {}).get(
17
+ "allowedClusterExternalConfigLabels", []
18
+ )
19
+ return set(allowed_labels)
20
+
21
+
15
22
  def fetch_current_state(clusters):
16
23
  settings = queries.get_app_interface_settings()
17
24
  ocm_map = OCMMap(
@@ -21,9 +28,12 @@ def fetch_current_state(clusters):
21
28
  current_state = []
22
29
  for cluster in clusters:
23
30
  cluster_name = cluster["name"]
31
+ allowed_labels = get_allowed_labels_for_cluster(cluster)
24
32
  ocm = ocm_map.get(cluster_name)
25
33
  labels = ocm.get_external_configuration_labels(cluster_name)
26
34
  for key, value in labels.items():
35
+ if key not in allowed_labels:
36
+ continue
27
37
  item = {"label": {"key": key, "value": value}, "cluster": cluster_name}
28
38
  current_state.append(item)
29
39
 
@@ -34,8 +44,13 @@ def fetch_desired_state(clusters):
34
44
  desired_state = []
35
45
  for cluster in clusters:
36
46
  cluster_name = cluster["name"]
47
+ allowed_labels = get_allowed_labels_for_cluster(cluster)
37
48
  labels = json.loads(cluster["externalConfiguration"]["labels"])
38
49
  for key, value in labels.items():
50
+ if key not in allowed_labels:
51
+ raise ValueError(
52
+ f"Unsupported external configuration label '{key}' in cluster '{cluster_name}'"
53
+ )
39
54
  item = {"label": {"key": key, "value": value}, "cluster": cluster_name}
40
55
  desired_state.append(item)
41
56
 
@@ -63,7 +63,7 @@ def fetch_desired_state(clusters, vault_input_path, settings):
63
63
 
64
64
 
65
65
  def sanitize(state):
66
- return {k: v for k, v in state.items() if k not in ["client_secret", "id"]}
66
+ return {k: v for k, v in state.items() if k not in {"client_secret", "id"}}
67
67
 
68
68
 
69
69
  def act(dry_run, ocm_map, current_state, desired_state):
reconcile/ocm_groups.py CHANGED
@@ -13,6 +13,7 @@ from reconcile import (
13
13
  from reconcile.status import ExitCodes
14
14
  from reconcile.utils.disabled_integrations import integration_is_enabled
15
15
  from reconcile.utils.ocm import OCMMap
16
+ from reconcile.utils.ocm.base import OCMClusterGroupId
16
17
 
17
18
  QONTRACT_INTEGRATION = "ocm-groups"
18
19
 
@@ -74,20 +75,39 @@ def run(dry_run, thread_pool_size=10):
74
75
  sys.exit(ExitCodes.SUCCESS)
75
76
 
76
77
  ocm_map, current_state = fetch_current_state(clusters, thread_pool_size)
77
- desired_state = openshift_groups.fetch_desired_state(oc_map=ocm_map)
78
+ desired_state = openshift_groups.fetch_desired_state(clusters=ocm_map.clusters())
78
79
 
79
- # we only manage dedicated-admins via OCM
80
- current_state = [s for s in current_state if s["group"] == "dedicated-admins"]
81
- desired_state = [s for s in desired_state if s["group"] == "dedicated-admins"]
80
+ current_state = [
81
+ s for s in current_state if s["group"] in OCMClusterGroupId.values()
82
+ ]
83
+ desired_state = [
84
+ s for s in desired_state if s["group"] in OCMClusterGroupId.values()
85
+ ]
82
86
 
83
87
  diffs = openshift_groups.calculate_diff(current_state, desired_state)
84
88
  openshift_groups.validate_diffs(diffs)
85
89
 
86
90
  for diff in diffs:
87
91
  # we do not need to create/delete groups in OCM
88
- if diff["action"] in ["create_group", "delete_group"]:
92
+ if diff["action"] in {"create_group", "delete_group"}:
89
93
  continue
90
94
  logging.info(list(diff.values()))
91
95
 
92
96
  if not dry_run:
93
97
  act(diff, ocm_map)
98
+
99
+
100
+ def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
101
+ clusters = [
102
+ c["name"]
103
+ for c in queries.get_clusters()
104
+ if integration_is_enabled(QONTRACT_INTEGRATION, c) and _cluster_is_compatible(c)
105
+ ]
106
+ desired_state = openshift_groups.fetch_desired_state(clusters=clusters)
107
+ desired_state = [
108
+ s for s in desired_state if s["group"] in OCMClusterGroupId.values()
109
+ ]
110
+
111
+ return {
112
+ "state": desired_state,
113
+ }
File without changes
@@ -0,0 +1,119 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from collections.abc import (
5
+ Callable,
6
+ )
7
+ from functools import lru_cache
8
+
9
+ from reconcile.gql_definitions.common.ocm_environments import (
10
+ query as ocm_environment_query,
11
+ )
12
+ from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment
13
+ from reconcile.slack_base import slackapi_from_queries
14
+ from reconcile.typed_queries.app_interface_custom_messages import (
15
+ get_app_interface_custom_message,
16
+ )
17
+ from reconcile.utils import gql
18
+ from reconcile.utils.ocm.search_filters import Filter
19
+ from reconcile.utils.ocm_base_client import (
20
+ init_ocm_base_client,
21
+ )
22
+ from reconcile.utils.runtime.integration import (
23
+ NoParams,
24
+ QontractReconcileIntegration,
25
+ )
26
+ from reconcile.utils.slack_api import UserNotFoundException
27
+
28
+ QONTRACT_INTEGRATION = "ocm-internal-notifications"
29
+
30
+
31
+ class OcmInternalNotifications(QontractReconcileIntegration[NoParams]):
32
+ """Notifications to internal Red Hat users based on conditions in OCM."""
33
+
34
+ def __init__(self) -> None:
35
+ super().__init__(NoParams())
36
+ self.slack = slackapi_from_queries(
37
+ integration_name=self.name, init_usergroups=False
38
+ )
39
+ self.slack_get_user_id_by_name = lru_cache()(self._slack_get_user_id_by_name)
40
+
41
+ @property
42
+ def name(self) -> str:
43
+ return QONTRACT_INTEGRATION
44
+
45
+ def get_environments(self, query_func: Callable) -> list[OCMEnvironment]:
46
+ return ocm_environment_query(query_func).environments
47
+
48
+ def _slack_get_user_id_by_name(
49
+ self, user_name: str, mail_address: str
50
+ ) -> str | None:
51
+ try:
52
+ return self.slack.get_user_id_by_name(
53
+ user_name=user_name, mail_address=mail_address
54
+ )
55
+ except UserNotFoundException:
56
+ return None
57
+
58
+ def run(self, dry_run: bool) -> None:
59
+ gqlapi = gql.get_api()
60
+ environments = self.get_environments(gqlapi.query)
61
+
62
+ for env in environments:
63
+ ocm = init_ocm_base_client(env, self.secret_reader)
64
+
65
+ if not (env.labels and env.labels.get("internal_notifications")):
66
+ logging.info(
67
+ f"skipping environment {env.name} due to no internal_notifications label"
68
+ )
69
+ continue
70
+
71
+ clusters = ocm.get(
72
+ api_path="/api/clusters_mgmt/v1/clusters",
73
+ params={
74
+ "search": Filter()
75
+ .eq("state", "uninstalling")
76
+ .eq("managed", "true")
77
+ .render(),
78
+ "orderBy": "created_at",
79
+ },
80
+ ).get("items")
81
+ subscriptions = ocm.get(
82
+ api_path="/api/accounts_mgmt/v1/subscriptions",
83
+ params={
84
+ "search": Filter()
85
+ .is_in("id", [c["subscription"]["id"] for c in clusters])
86
+ .render(),
87
+ "orderBy": "created_at",
88
+ },
89
+ ).get("items")
90
+
91
+ slack_user_ids = set()
92
+ for subscription in subscriptions:
93
+ creator = ocm.get(api_path=subscription["creator"]["href"])
94
+ email = creator["email"]
95
+ logging.info(
96
+ f"found managed cluster in uninstalling state in environment {env.name} with creator {email}"
97
+ )
98
+ user, mail_address = email.split("@")
99
+ user_name = user.split("+")[0]
100
+ slack_user_id = self.slack_get_user_id_by_name(user_name, mail_address)
101
+ if slack_user_id:
102
+ logging.info(
103
+ f"found slack user id {slack_user_id} for user {user_name}"
104
+ )
105
+ slack_user_ids.add(slack_user_id)
106
+ else:
107
+ logging.warning(f"slack user id not found for user {user_name}")
108
+
109
+ if not dry_run and slack_user_ids:
110
+ users = " ".join([f"<@{uid}>" for uid in slack_user_ids])
111
+ instructions = (
112
+ get_app_interface_custom_message(
113
+ "ocm-internal-notifications-instructions"
114
+ )
115
+ or ""
116
+ )
117
+ self.slack.chat_post_message(
118
+ f"hey {users} :wave: you have clusters stuck in uninstalling state in the {env.name} environment. {instructions}"
119
+ )
File without changes