qontract-reconcile 0.9.1rc298__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 (843) 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.9.1rc298.dist-info → qontract_reconcile-0.10.1.dev1203.dist-info}/WHEEL +1 -2
  4. {qontract_reconcile-0.9.1rc298.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.9.1rc298.dist-info/METADATA +0 -63
  676. qontract_reconcile-0.9.1rc298.dist-info/RECORD +0 -585
  677. qontract_reconcile-0.9.1rc298.dist-info/top_level.txt +0 -4
  678. reconcile/ecr_mirror.py +0 -152
  679. reconcile/github_scanner.py +0 -74
  680. reconcile/gitlab_integrations.py +0 -63
  681. reconcile/gql_definitions/ocm_oidc_idp/clusters.py +0 -195
  682. reconcile/gql_definitions/ocp_release_mirror/ocp_release_mirror.py +0 -287
  683. reconcile/integrations_validator.py +0 -18
  684. reconcile/jenkins_plugins.py +0 -129
  685. reconcile/kafka_clusters.py +0 -208
  686. reconcile/ocm_cluster_admin.py +0 -42
  687. reconcile/ocm_oidc_idp.py +0 -198
  688. reconcile/ocp_release_mirror.py +0 -373
  689. reconcile/prometheus_rules_tester_old.py +0 -436
  690. reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager.py +0 -279
  691. reconcile/saas_auto_promotions_manager/utils/vcs.py +0 -141
  692. reconcile/sentry_config.py +0 -613
  693. reconcile/sentry_helper.py +0 -69
  694. reconcile/test/conftest.py +0 -187
  695. reconcile/test/fixtures.py +0 -24
  696. reconcile/test/saas_auto_promotions_manager/conftest.py +0 -69
  697. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py +0 -110
  698. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/data_keys.py +0 -10
  699. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_housekeeping.py +0 -200
  700. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py +0 -151
  701. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +0 -63
  702. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/data_keys.py +0 -4
  703. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_multiple_namespaces.py +0 -46
  704. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_namespace.py +0 -94
  705. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_target.py +0 -44
  706. reconcile/test/saas_auto_promotions_manager/subscriber/conftest.py +0 -74
  707. reconcile/test/saas_auto_promotions_manager/subscriber/data_keys.py +0 -11
  708. reconcile/test/saas_auto_promotions_manager/subscriber/test_content_hash.py +0 -155
  709. reconcile/test/saas_auto_promotions_manager/subscriber/test_diff.py +0 -173
  710. reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_config_hash.py +0 -226
  711. reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_moving_ref.py +0 -224
  712. reconcile/test/saas_auto_promotions_manager/subscriber/test_single_channel_with_single_publisher.py +0 -350
  713. reconcile/test/saas_auto_promotions_manager/test_integration_test.py +0 -129
  714. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_multiple_publishers_for_single_channel.py +0 -70
  715. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_use_target_config_hash.py +0 -63
  716. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_with_auto_promote.py +0 -74
  717. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_without_auto_promote.py +0 -65
  718. reconcile/test/test_aggregated_list.py +0 -237
  719. reconcile/test/test_amtool.py +0 -37
  720. reconcile/test/test_auto_promoter.py +0 -295
  721. reconcile/test/test_aws_ami_share.py +0 -68
  722. reconcile/test/test_aws_iam_keys.py +0 -70
  723. reconcile/test/test_aws_iam_password_reset.py +0 -35
  724. reconcile/test/test_aws_support_cases_sos.py +0 -23
  725. reconcile/test/test_checkpoint.py +0 -178
  726. reconcile/test/test_cli.py +0 -41
  727. reconcile/test/test_closedbox_endpoint_monitoring.py +0 -207
  728. reconcile/test/test_gabi_authorized_users.py +0 -72
  729. reconcile/test/test_github_org.py +0 -154
  730. reconcile/test/test_github_repo_invites.py +0 -123
  731. reconcile/test/test_gitlab_housekeeping.py +0 -88
  732. reconcile/test/test_gitlab_labeler.py +0 -129
  733. reconcile/test/test_gitlab_members.py +0 -283
  734. reconcile/test/test_instrumented_wrappers.py +0 -18
  735. reconcile/test/test_integrations_manager.py +0 -995
  736. reconcile/test/test_jenkins_worker_fleets.py +0 -55
  737. reconcile/test/test_jump_host.py +0 -117
  738. reconcile/test/test_ldap_users.py +0 -123
  739. reconcile/test/test_make.py +0 -28
  740. reconcile/test/test_ocm_additional_routers.py +0 -134
  741. reconcile/test/test_ocm_addons_upgrade_scheduler_org.py +0 -149
  742. reconcile/test/test_ocm_clusters.py +0 -598
  743. reconcile/test/test_ocm_clusters_manifest_updates.py +0 -89
  744. reconcile/test/test_ocm_oidc_idp.py +0 -315
  745. reconcile/test/test_ocm_update_recommended_version.py +0 -145
  746. reconcile/test/test_ocm_upgrade_scheduler.py +0 -614
  747. reconcile/test/test_ocm_upgrade_scheduler_org_updater.py +0 -129
  748. reconcile/test/test_openshift_base.py +0 -730
  749. reconcile/test/test_openshift_namespace_labels.py +0 -345
  750. reconcile/test/test_openshift_namespaces.py +0 -256
  751. reconcile/test/test_openshift_resource.py +0 -415
  752. reconcile/test/test_openshift_resources_base.py +0 -440
  753. reconcile/test/test_openshift_saas_deploy_change_tester.py +0 -310
  754. reconcile/test/test_openshift_tekton_resources.py +0 -253
  755. reconcile/test/test_openshift_upgrade_watcher.py +0 -146
  756. reconcile/test/test_prometheus_rules_tester.py +0 -151
  757. reconcile/test/test_prometheus_rules_tester_old.py +0 -77
  758. reconcile/test/test_quay_membership.py +0 -86
  759. reconcile/test/test_quay_mirror.py +0 -109
  760. reconcile/test/test_quay_mirror_org.py +0 -70
  761. reconcile/test/test_quay_repos.py +0 -59
  762. reconcile/test/test_queries.py +0 -53
  763. reconcile/test/test_repo_owners.py +0 -47
  764. reconcile/test/test_requests_sender.py +0 -139
  765. reconcile/test/test_saasherder.py +0 -1074
  766. reconcile/test/test_saasherder_allowed_secret_paths.py +0 -127
  767. reconcile/test/test_secret_reader.py +0 -153
  768. reconcile/test/test_slack_base.py +0 -185
  769. reconcile/test/test_slack_usergroups.py +0 -744
  770. reconcile/test/test_sql_query.py +0 -19
  771. reconcile/test/test_terraform_cloudflare_dns.py +0 -117
  772. reconcile/test/test_terraform_cloudflare_resources.py +0 -106
  773. reconcile/test/test_terraform_cloudflare_users.py +0 -749
  774. reconcile/test/test_terraform_resources.py +0 -257
  775. reconcile/test/test_terraform_tgw_attachments.py +0 -631
  776. reconcile/test/test_terraform_users.py +0 -57
  777. reconcile/test/test_terraform_vpc_peerings.py +0 -499
  778. reconcile/test/test_terraform_vpc_peerings_build_desired_state.py +0 -1061
  779. reconcile/test/test_unleash.py +0 -138
  780. reconcile/test/test_utils_aws_api.py +0 -240
  781. reconcile/test/test_utils_aws_helper.py +0 -80
  782. reconcile/test/test_utils_cluster_version_data.py +0 -177
  783. reconcile/test/test_utils_data_structures.py +0 -13
  784. reconcile/test/test_utils_disabled_integrations.py +0 -86
  785. reconcile/test/test_utils_expiration.py +0 -109
  786. reconcile/test/test_utils_external_resource_spec.py +0 -383
  787. reconcile/test/test_utils_external_resources.py +0 -247
  788. reconcile/test/test_utils_github_api.py +0 -73
  789. reconcile/test/test_utils_gitlab_api.py +0 -20
  790. reconcile/test/test_utils_gpg.py +0 -69
  791. reconcile/test/test_utils_gql.py +0 -81
  792. reconcile/test/test_utils_helm.py +0 -306
  793. reconcile/test/test_utils_helpers.py +0 -55
  794. reconcile/test/test_utils_imap_client.py +0 -65
  795. reconcile/test/test_utils_jjb_client.py +0 -52
  796. reconcile/test/test_utils_jsonpath.py +0 -286
  797. reconcile/test/test_utils_ldap_client.py +0 -51
  798. reconcile/test/test_utils_mr.py +0 -226
  799. reconcile/test/test_utils_mr_clusters_updates.py +0 -77
  800. reconcile/test/test_utils_oc.py +0 -984
  801. reconcile/test/test_utils_ocm.py +0 -110
  802. reconcile/test/test_utils_pagerduty_api.py +0 -251
  803. reconcile/test/test_utils_parse_dhms_duration.py +0 -34
  804. reconcile/test/test_utils_password_validator.py +0 -155
  805. reconcile/test/test_utils_quay_api.py +0 -86
  806. reconcile/test/test_utils_semver_helper.py +0 -19
  807. reconcile/test/test_utils_sharding.py +0 -56
  808. reconcile/test/test_utils_slack_api.py +0 -439
  809. reconcile/test/test_utils_smtp_client.py +0 -73
  810. reconcile/test/test_utils_state.py +0 -256
  811. reconcile/test/test_utils_terraform.py +0 -13
  812. reconcile/test/test_utils_terraform_client.py +0 -585
  813. reconcile/test/test_utils_terraform_config_client.py +0 -219
  814. reconcile/test/test_utils_terrascript_aws_client.py +0 -277
  815. reconcile/test/test_utils_terrascript_cloudflare_client.py +0 -597
  816. reconcile/test/test_utils_terrascript_cloudflare_resources.py +0 -26
  817. reconcile/test/test_vault_replication.py +0 -515
  818. reconcile/test/test_vault_utils.py +0 -47
  819. reconcile/test/test_version_bump.py +0 -18
  820. reconcile/test/test_vpc_peerings_validator.py +0 -103
  821. reconcile/test/test_wrong_region.py +0 -78
  822. reconcile/typed_queries/glitchtip_settings.py +0 -18
  823. reconcile/typed_queries/ocp_release_mirror.py +0 -11
  824. reconcile/unleash_watcher.py +0 -120
  825. reconcile/utils/git_secrets.py +0 -63
  826. reconcile/utils/mr/auto_promoter.py +0 -218
  827. reconcile/utils/sentry_client.py +0 -383
  828. release/test_version.py +0 -50
  829. release/version.py +0 -100
  830. tools/test/test_qontract_cli.py +0 -60
  831. tools/test/test_sre_checkpoints.py +0 -79
  832. /e2e_tests/__init__.py → /reconcile/aus/upgrades.py +0 -0
  833. /reconcile/{gql_definitions/ocp_release_mirror → aws_account_manager}/__init__.py +0 -0
  834. /reconcile/{test → aws_ami_cleanup}/__init__.py +0 -0
  835. /reconcile/{test/saas_auto_promotions_manager → aws_cloudwatch_log_retention}/__init__.py +0 -0
  836. /reconcile/{test/saas_auto_promotions_manager/merge_request_manager → aws_saml_idp}/__init__.py +0 -0
  837. /reconcile/{test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager → aws_saml_roles}/__init__.py +0 -0
  838. /reconcile/{test/saas_auto_promotions_manager/merge_request_manager/renderer → aws_version_sync}/__init__.py +0 -0
  839. /reconcile/{test/saas_auto_promotions_manager/subscriber → aws_version_sync/merge_request_manager}/__init__.py +0 -0
  840. /reconcile/{test/saas_auto_promotions_manager/utils → cluster_auth_rhidp}/__init__.py +0 -0
  841. /reconcile/{test/saas_auto_promotions_manager/utils/saas_files_inventory → dynatrace_token_provider}/__init__.py +0 -0
  842. {release → reconcile/endpoints_discovery}/__init__.py +0 -0
  843. {tools/test → reconcile/external_resources}/__init__.py +0 -0
@@ -1,25 +1,638 @@
1
+ import logging
2
+ from collections import defaultdict
3
+ from datetime import timedelta
1
4
  from typing import Optional
2
5
 
3
- from reconcile.aus.models import OrganizationUpgradeSpec
6
+ from pydantic import (
7
+ BaseModel,
8
+ Field,
9
+ ValidationError,
10
+ validator,
11
+ )
12
+ from pydantic.dataclasses import dataclass
13
+
14
+ from reconcile.aus.healthchecks import (
15
+ AUSClusterHealthCheckProvider,
16
+ build_cluster_health_providers_for_organization,
17
+ )
18
+ from reconcile.aus.metrics import AUSOCMEnvironmentError
19
+ from reconcile.aus.models import (
20
+ ClusterUpgradeSpec,
21
+ NodePoolSpec,
22
+ OrganizationUpgradeSpec,
23
+ )
24
+ from reconcile.aus.node_pool_spec import (
25
+ get_node_pool_specs_by_org_cluster,
26
+ )
4
27
  from reconcile.aus.ocm_upgrade_scheduler_org import (
5
28
  OCMClusterUpgradeSchedulerOrgIntegration,
6
29
  )
30
+ from reconcile.gql_definitions.fragments.aus_organization import (
31
+ AUSOCMOrganization,
32
+ OpenShiftClusterManagerSectorDependenciesV1,
33
+ OpenShiftClusterManagerSectorV1,
34
+ OpenShiftClusterManagerV1_OpenShiftClusterManagerV1,
35
+ OpenShiftClusterManagerV1_OpenShiftClusterManagerV1_OpenShiftClusterManagerEnvironmentV1,
36
+ )
37
+ from reconcile.gql_definitions.fragments.minimal_ocm_organization import (
38
+ MinimalOCMOrganization,
39
+ )
7
40
  from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment
41
+ from reconcile.gql_definitions.fragments.upgrade_policy import (
42
+ ClusterUpgradePolicyConditionsV1,
43
+ ClusterUpgradePolicyV1,
44
+ )
45
+ from reconcile.utils import metrics
46
+ from reconcile.utils.clusterhealth.providerbase import ClusterHealthProvider
47
+ from reconcile.utils.models import (
48
+ CSV,
49
+ cron_validator,
50
+ )
51
+ from reconcile.utils.ocm.base import (
52
+ LabelContainer,
53
+ OCMClusterServiceLogCreateModel,
54
+ OCMOrganizationLabel,
55
+ OCMServiceLogSeverity,
56
+ build_label_container,
57
+ )
58
+ from reconcile.utils.ocm.clusters import (
59
+ ClusterDetails,
60
+ discover_clusters_by_labels,
61
+ )
62
+ from reconcile.utils.ocm.labels import (
63
+ get_org_labels,
64
+ get_organization_labels,
65
+ subscription_label_filter,
66
+ )
67
+ from reconcile.utils.ocm.search_filters import Filter
68
+ from reconcile.utils.ocm.service_log import create_service_log
69
+ from reconcile.utils.ocm.sre_capability_labels import (
70
+ build_labelset,
71
+ labelset_groupfield,
72
+ sre_capability_label_key,
73
+ )
74
+ from reconcile.utils.ocm_base_client import (
75
+ OCMBaseClient,
76
+ init_ocm_base_client,
77
+ )
8
78
 
9
79
  QONTRACT_INTEGRATION = "advanced-upgrade-scheduler"
10
80
 
11
81
 
12
82
  class AdvancedUpgradeServiceIntegration(OCMClusterUpgradeSchedulerOrgIntegration):
83
+ """
84
+ A flavour of the OCM organization based upgrade scheduler, that uses
85
+ OCM labels to discover clusters and their upgrade policies.
86
+ """
87
+
13
88
  @property
14
89
  def name(self) -> str:
15
90
  return QONTRACT_INTEGRATION
16
91
 
17
- def get_ocm_env_upgrade_specs(
18
- self, ocm_env: OCMEnvironment, org_name: Optional[str] = None
92
+ def get_upgrade_specs(self) -> dict[str, dict[str, OrganizationUpgradeSpec]]:
93
+ inheritance_network = self.init_version_data_network()
94
+ envs_org_upgrade_specs: dict[str, dict[str, OrganizationUpgradeSpec]] = {}
95
+ for ocm_env in self.get_ocm_environments():
96
+ try:
97
+ envs_org_upgrade_specs[ocm_env.name] = (
98
+ self._build_ocm_env_upgrade_specs(
99
+ ocm_env=ocm_env,
100
+ inheritance_network=inheritance_network,
101
+ )
102
+ )
103
+ except Exception as e:
104
+ logging.exception(
105
+ "Failed to get org upgrade specs for OCM environment %s. Skipping. %s",
106
+ ocm_env.name,
107
+ e,
108
+ )
109
+ metrics.inc_counter(
110
+ AUSOCMEnvironmentError(
111
+ integration=self.name,
112
+ ocm_env=ocm_env.name,
113
+ )
114
+ )
115
+ return envs_org_upgrade_specs
116
+
117
+ def init_version_data_network(self) -> dict["OrgRef", "VersionDataInheritance"]:
118
+ # collect all version data labels from all OCM environments ...
119
+ org_to_env: dict[str, OCMEnvironment] = {}
120
+ labels_by_org: dict[str, list[OCMOrganizationLabel]] = defaultdict(list)
121
+ for env in self.get_ocm_environments(filter=False):
122
+ with init_ocm_base_client(env, self.secret_reader) as ocm_api:
123
+ for label in get_organization_labels(
124
+ ocm_api=ocm_api,
125
+ filter=Filter().like("key", aus_label_key("version-data.%")),
126
+ ):
127
+ labels_by_org[label.organization_id].append(label)
128
+ org_to_env[label.organization_id] = env
129
+
130
+ # ... and build the inheritance network
131
+ return build_version_data_inheritance_network({
132
+ OrgRef(
133
+ org_id=org_id, env_name=org_to_env[org_id].name
134
+ ): build_label_container(labels)
135
+ for org_id, labels in labels_by_org.items()
136
+ })
137
+
138
+ def _build_ocm_env_upgrade_specs(
139
+ self,
140
+ ocm_env: OCMEnvironment,
141
+ inheritance_network: dict["OrgRef", "VersionDataInheritance"],
19
142
  ) -> dict[str, OrganizationUpgradeSpec]:
20
- return {
21
- # todo
22
- # discover orgs + clusters via labels
23
- # and create OrganizationUpgradeSpec objects
24
- # from them
143
+ organizations = {
144
+ org.org_id: org for org in self.get_orgs_for_environment(ocm_env)
25
145
  }
146
+ with init_ocm_base_client(ocm_env, self.secret_reader) as ocm_api:
147
+ clusters_by_org = discover_clusters(
148
+ ocm_api=ocm_api,
149
+ org_ids=set(organizations.keys()),
150
+ ignore_sts_clusters=self.params.ignore_sts_clusters,
151
+ )
152
+ labels_by_org = _get_org_labels(
153
+ ocm_api=ocm_api, org_ids=set(organizations.keys())
154
+ )
155
+ node_pool_specs_by_org_cluster = get_node_pool_specs_by_org_cluster(
156
+ ocm_api, clusters_by_org
157
+ )
158
+
159
+ cluster_health_providers = self._health_check_providers_for_env(ocm_env.name)
160
+
161
+ return _build_org_upgrade_specs_for_ocm_env(
162
+ orgs=organizations,
163
+ clusters_by_org=clusters_by_org,
164
+ labels_by_org=labels_by_org,
165
+ inheritance_network={
166
+ org_ref.org_id: vdi for org_ref, vdi in inheritance_network.items()
167
+ },
168
+ cluster_health_providers=cluster_health_providers,
169
+ node_pool_specs_by_org_cluster=node_pool_specs_by_org_cluster,
170
+ )
171
+
172
+ def signal_validation_issues(
173
+ self, dry_run: bool, org_upgrade_spec: OrganizationUpgradeSpec
174
+ ) -> None:
175
+ if not dry_run:
176
+ with init_ocm_base_client(
177
+ org_upgrade_spec.org.environment, self.secret_reader
178
+ ) as ocm_api:
179
+ _signal_validation_issues_for_org(
180
+ ocm_api=ocm_api, org_upgrade_spec=org_upgrade_spec
181
+ )
182
+
183
+ def signal_reconcile_issues(
184
+ self,
185
+ dry_run: bool,
186
+ org_upgrade_spec: OrganizationUpgradeSpec,
187
+ exception: Exception,
188
+ ) -> bool:
189
+ """
190
+ AUS will not fail on a reconcile issue. If issues should be noticed by an SRE team,
191
+ alerts based on the metrics in the `reconcile.aus.metrics` module should be set up.
192
+
193
+ The function is an override on the default behaviour to not ignore errors.
194
+ It returns true to indicate that the exception was properly handled by logging it.
195
+ Users / org owners will not be notified about the exception via service logs.
196
+ AppSRE team members will be notified about the exception via the logs.
197
+
198
+ """
199
+ logging.error(
200
+ f"Failed to reconcile cluster upgrades in OCM organization {org_upgrade_spec.org.org_id}",
201
+ exc_info=exception,
202
+ )
203
+ return True
204
+
205
+
206
+ def discover_clusters(
207
+ ocm_api: OCMBaseClient,
208
+ org_ids: set[str] | None = None,
209
+ ignore_sts_clusters: bool = False,
210
+ ) -> dict[str, list[ClusterDetails]]:
211
+ """
212
+ Discover all clusters that are part of the AUS service.
213
+ Discovery is driven by OCM cluster labels.
214
+ """
215
+ clusters = discover_clusters_by_labels(
216
+ ocm_api=ocm_api,
217
+ label_filter=subscription_label_filter().like("key", aus_label_key("%")),
218
+ )
219
+
220
+ # group by org and filter if org_id is specified
221
+ clusters_by_org: dict[str, list[ClusterDetails]] = defaultdict(list)
222
+ for c in clusters:
223
+ is_sts_cluster = c.ocm_cluster.aws and c.ocm_cluster.aws.sts_enabled
224
+ passed_sts_filter = not ignore_sts_clusters or not is_sts_cluster
225
+ passed_ocm_filters = not org_ids or c.organization_id in org_ids
226
+ if passed_ocm_filters and passed_sts_filter:
227
+ clusters_by_org[c.organization_id].append(c)
228
+
229
+ return clusters_by_org
230
+
231
+
232
+ def _get_org_labels(
233
+ ocm_api: OCMBaseClient, org_ids: set[str] | None
234
+ ) -> dict[str, LabelContainer]:
235
+ """
236
+ Fetch all AUS OCM org labels from organizations. They hold config
237
+ parameters like blocked versions etc.
238
+
239
+ The result is a dict with organization IDs as keys and label containers as values.
240
+ """
241
+ return get_org_labels(
242
+ ocm_api=ocm_api,
243
+ org_ids=org_ids or set(),
244
+ label_filter=Filter().like("key", aus_label_key("%")),
245
+ )
246
+
247
+
248
+ def _build_org_upgrade_specs_for_ocm_env(
249
+ orgs: dict[str, AUSOCMOrganization],
250
+ clusters_by_org: dict[str, list[ClusterDetails]],
251
+ labels_by_org: dict[str, LabelContainer],
252
+ inheritance_network: dict[str, "VersionDataInheritance"],
253
+ cluster_health_providers: dict[str, ClusterHealthProvider],
254
+ node_pool_specs_by_org_cluster: dict[str, dict[str, list[NodePoolSpec]]],
255
+ ) -> dict[str, OrganizationUpgradeSpec]:
256
+ """
257
+ Builds the cluster upgrade specs for the given OCM environment.
258
+ The specs are returned grouped by organization.
259
+ """
260
+ return {
261
+ org_id: _build_org_upgrade_spec(
262
+ org=orgs[org_id],
263
+ clusters=clusters,
264
+ org_labels=labels_by_org.get(org_id) or build_label_container(),
265
+ version_data_inheritance=inheritance_network.get(org_id),
266
+ cluster_health_provider=build_cluster_health_providers_for_organization(
267
+ org=orgs[org_id],
268
+ providers=cluster_health_providers,
269
+ ),
270
+ node_pool_specs_by_cluster_id=node_pool_specs_by_org_cluster.get(org_id)
271
+ or {},
272
+ )
273
+ for org_id, clusters in clusters_by_org.items()
274
+ }
275
+
276
+
277
+ def aus_label_key(config_atom: str | None = None) -> str:
278
+ """
279
+ Generates label keys for aus, compliant with the naming schema defined in
280
+ https://service.pages.redhat.com/dev-guidelines/docs/sre-capabilities/framework/ocm-labels/
281
+ """
282
+ return sre_capability_label_key("aus", config_atom)
283
+
284
+
285
+ class OrganizationLabelSet(BaseModel):
286
+ """
287
+ Parses, represents and validates a set of organization labels for AUS.
288
+ """
289
+
290
+ blocked_versions: CSV | None = Field(alias=aus_label_key("blocked-versions"))
291
+
292
+ sector_deps: dict[str, CSV] = labelset_groupfield(
293
+ group_prefix=aus_label_key("sector-deps.")
294
+ )
295
+ """
296
+ Each sector with dependencies is represented as a `sector-deps.<sector-name>` label
297
+ with a CSV formatted list of dependant sectors. The custom `labelset_groupfield``
298
+ FieldMeta combined with the CSV field type takes care of grouping and parsing
299
+ labels into a dict where each sector is a key and their dependencies are the value.
300
+ """
301
+
302
+ def sector_dependencies(self) -> list[OpenShiftClusterManagerSectorV1]:
303
+ """
304
+ Transforms the sector dependencies into the appropriate dataclasses
305
+ required by the upgrade policy spec.
306
+ """
307
+ all_sectors = set()
308
+ for s, deps in self.sector_deps.items():
309
+ all_sectors.add(s)
310
+ all_sectors.update(deps)
311
+ return [
312
+ OpenShiftClusterManagerSectorV1(
313
+ name=s,
314
+ dependencies=[
315
+ OpenShiftClusterManagerSectorDependenciesV1(name=d, ocm=None)
316
+ for d in self.sector_deps.get(s, [])
317
+ ],
318
+ )
319
+ for s in all_sectors
320
+ ]
321
+
322
+
323
+ def _build_org_upgrade_spec(
324
+ org: AUSOCMOrganization,
325
+ clusters: list[ClusterDetails],
326
+ org_labels: LabelContainer,
327
+ version_data_inheritance: Optional["VersionDataInheritance"],
328
+ cluster_health_provider: AUSClusterHealthCheckProvider,
329
+ node_pool_specs_by_cluster_id: dict[str, list[NodePoolSpec]],
330
+ ) -> OrganizationUpgradeSpec:
331
+ """
332
+ Build a upgrade policy spec for each cluster in the organization that
333
+ has a valid set of labels. Clusters without a set of labels are ignored. Clusters
334
+ with an invalid/incomplete set of labels are reported as an error.
335
+ """
336
+
337
+ # build version inheritance config
338
+ inherit_version_data = None
339
+ if version_data_inheritance and version_data_inheritance.inherit_from_orgs:
340
+ inherit_version_data = [
341
+ OpenShiftClusterManagerV1_OpenShiftClusterManagerV1(
342
+ name=source_org_ref.org_id,
343
+ orgId=source_org_ref.org_id,
344
+ environment=OpenShiftClusterManagerV1_OpenShiftClusterManagerV1_OpenShiftClusterManagerEnvironmentV1(
345
+ name=source_org_ref.env_name
346
+ ),
347
+ publishVersionData=[
348
+ MinimalOCMOrganization(orgId=org.org_id, name=org.name)
349
+ ],
350
+ )
351
+ for source_org_ref in version_data_inheritance.inherit_from_orgs
352
+ ]
353
+
354
+ org_labelset = build_labelset(org_labels, OrganizationLabelSet)
355
+ final_org = org.copy(deep=True)
356
+ final_org.blocked_versions = org_labelset.blocked_versions
357
+ final_org.sectors = org_labelset.sector_dependencies()
358
+ final_org.inherit_version_data = inherit_version_data
359
+ org_upgrade_spec = OrganizationUpgradeSpec(org=final_org)
360
+
361
+ # init policy for each cluster
362
+ for c in clusters:
363
+ try:
364
+ upgrade_policy = _build_policy_from_labels(c.labels)
365
+ cluster_health = cluster_health_provider.cluster_health(
366
+ cluster_external_id=c.ocm_cluster.external_id, org_id=org.org_id
367
+ )
368
+ org_upgrade_spec.add_spec(
369
+ ClusterUpgradeSpec(
370
+ org=org_upgrade_spec.org,
371
+ upgradePolicy=upgrade_policy,
372
+ cluster=c.ocm_cluster,
373
+ health=cluster_health,
374
+ nodePools=node_pool_specs_by_cluster_id.get(c.ocm_cluster.id) or [],
375
+ )
376
+ )
377
+ except ValidationError as validation_error:
378
+ for e in validation_error.errors():
379
+ org_upgrade_spec.add_cluster_error(
380
+ c.ocm_cluster.external_id, f"label {e['loc'][0]}: {e['msg']}"
381
+ )
382
+ except Exception as ex:
383
+ org_upgrade_spec.add_cluster_error(c.ocm_cluster.external_id, str(ex))
384
+
385
+ # register organization errors
386
+ if (
387
+ version_data_inheritance
388
+ and version_data_inheritance.unverified_inheritance_from_orgs
389
+ ):
390
+ unverified_org_ids = [
391
+ org.org_id
392
+ for org in version_data_inheritance.unverified_inheritance_from_orgs
393
+ ]
394
+ org_upgrade_spec.add_organization_error(
395
+ f"Version data inheritance from organizations {', '.join(sorted(unverified_org_ids))} "
396
+ f"are unverified. Ask the owner of these organizations to publish version data to the organization ID {org.org_id}. "
397
+ "See https://source.redhat.com/groups/public/sre/wiki/advanced_upgrade_service_aus"
398
+ )
399
+
400
+ return org_upgrade_spec
401
+
402
+
403
+ class ClusterUpgradePolicyLabelSet(BaseModel):
404
+ """
405
+ Parses, represents and validates a set of subscription labels for AUS.
406
+ """
407
+
408
+ soak_days: int = Field(alias=aus_label_key("soak-days"), ge=0)
409
+ workloads: CSV = Field(alias=aus_label_key("workloads"), csv_min_items=1)
410
+ schedule: str = Field(alias=aus_label_key("schedule"))
411
+ mutexes: CSV | None = Field(alias=aus_label_key("mutexes"))
412
+ sector: str | None = Field(alias=aus_label_key("sector"))
413
+ blocked_versions: CSV | None = Field(alias=aus_label_key("blocked-versions"))
414
+ version_gate_approvals: CSV | None = Field(
415
+ alias=aus_label_key("version-gate-approvals")
416
+ )
417
+ _schedule_validator = validator("schedule", allow_reuse=True)(cron_validator)
418
+
419
+ def build_labels_dict(self) -> dict[str, str]:
420
+ """
421
+ Build a dictionary of all labels in this labelset.
422
+ """
423
+ labels = {}
424
+ for k, v in self.dict(by_alias=True).items():
425
+ if v is None:
426
+ continue
427
+ if isinstance(v, list):
428
+ labels[k] = ",".join(sorted(v))
429
+ else:
430
+ labels[k] = str(v)
431
+ return labels
432
+
433
+
434
+ def build_cluster_upgrade_policy_label_set(
435
+ workloads: list[str],
436
+ schedule: str,
437
+ soak_days: int,
438
+ mutexes: list[str] | None = None,
439
+ sector: str | None = None,
440
+ blocked_versions: list[str] | None = None,
441
+ version_gate_approvals: list[str] | None = None,
442
+ ) -> ClusterUpgradePolicyLabelSet:
443
+ return ClusterUpgradePolicyLabelSet(**{
444
+ aus_label_key("workloads"): ",".join(workloads),
445
+ aus_label_key("schedule"): schedule,
446
+ aus_label_key("soak-days"): soak_days,
447
+ aus_label_key("mutexes"): ",".join(mutexes) if mutexes else None,
448
+ aus_label_key("sector"): sector,
449
+ aus_label_key("blocked-versions"): ",".join(blocked_versions)
450
+ if blocked_versions
451
+ else None,
452
+ aus_label_key("version-gate-approvals"): ",".join(version_gate_approvals)
453
+ if version_gate_approvals
454
+ else None,
455
+ })
456
+
457
+
458
+ def _build_policy_from_labels(labels: LabelContainer) -> ClusterUpgradePolicyV1:
459
+ """
460
+ Build a cluster upgrade policy object from a set of OCM labels. Parsing
461
+ and validation of the labels is delegated to the pydantic dataclass
462
+ ClusterUpgradePolicyLabelSet.
463
+ """
464
+ policy_labelset = build_labelset(labels, ClusterUpgradePolicyLabelSet)
465
+ return ClusterUpgradePolicyV1(
466
+ workloads=policy_labelset.workloads,
467
+ versionGateApprovals=policy_labelset.version_gate_approvals,
468
+ schedule=policy_labelset.schedule,
469
+ conditions=ClusterUpgradePolicyConditionsV1(
470
+ soakDays=policy_labelset.soak_days,
471
+ mutexes=policy_labelset.mutexes,
472
+ sector=policy_labelset.sector,
473
+ blockedVersions=policy_labelset.blocked_versions,
474
+ ),
475
+ )
476
+
477
+
478
+ class VersionDataInheritanceLabelSet(BaseModel):
479
+ inherit_version_data: CSV | None = Field(
480
+ alias=aus_label_key("version-data.inherit")
481
+ )
482
+ """
483
+ A list of OCM organization IDs to inherit version data from. These organization also need
484
+ to publish their version data via the `publish-version-data` label to the inheriting version.
485
+ Version data publishing/inheritance can also be defined between OCM environments.
486
+ """
487
+
488
+ publish_version_data: CSV | None = Field(
489
+ alias=aus_label_key("version-data.publish")
490
+ )
491
+ """
492
+ A list of OCM organization IDs to publish version data to. These organization also need
493
+ to explicitely inherit version data via the `inherit-version-data` label from this organization.
494
+ Version data publishing/inheritance can also be defined between OCM environments.
495
+ """
496
+
497
+
498
+ @dataclass(frozen=True, eq=True)
499
+ class OrgRef:
500
+ org_id: str
501
+ env_name: str
502
+
503
+
504
+ class VersionDataInheritance(BaseModel):
505
+ org_id: str
506
+ inherit_from_orgs: set[OrgRef]
507
+ unverified_inheritance_from_orgs: set[OrgRef]
508
+
509
+
510
+ def build_version_data_inheritance_network(
511
+ labels_per_org: dict[OrgRef, LabelContainer],
512
+ ) -> dict[OrgRef, VersionDataInheritance]:
513
+ """
514
+ Validates publish/inherit relationships between OCM organizations and environments from the
515
+ provided label containers.
516
+
517
+ This function returns a dictionary of OCM organizations and their version data
518
+ inheritance relationships.
519
+ """
520
+ label_set_per_org = {
521
+ org_ref: build_labelset(labels, VersionDataInheritanceLabelSet)
522
+ for org_ref, labels in labels_per_org.items()
523
+ }
524
+ org_ref_lookup = {org_ref.org_id: org_ref for org_ref in labels_per_org}
525
+
526
+ return {
527
+ org_ref: _build_version_data_inheritance(
528
+ org_ref,
529
+ label_set,
530
+ org_ref_lookup,
531
+ label_set_per_org,
532
+ )
533
+ for org_ref, label_set in label_set_per_org.items()
534
+ if label_set.inherit_version_data
535
+ }
536
+
537
+
538
+ def _build_version_data_inheritance(
539
+ org_ref: OrgRef,
540
+ label_set: VersionDataInheritanceLabelSet,
541
+ org_ref_lookup: dict[str, OrgRef],
542
+ label_set_per_org: dict[OrgRef, VersionDataInheritanceLabelSet],
543
+ ) -> VersionDataInheritance:
544
+ inherit_from_orgs_org_ids = {
545
+ source_org_id
546
+ for source_org_id in label_set.inherit_version_data or []
547
+ if source_org_id in org_ref_lookup
548
+ and org_ref.org_id
549
+ in (label_set_per_org[org_ref_lookup[source_org_id]].publish_version_data or [])
550
+ }
551
+ unverified_inheritance_from_orgs_org_ids = (
552
+ set(label_set.inherit_version_data or []) - inherit_from_orgs_org_ids
553
+ )
554
+
555
+ return VersionDataInheritance(
556
+ org_id=org_ref.org_id,
557
+ inherit_from_orgs={
558
+ org_ref_lookup[source_org_id] for source_org_id in inherit_from_orgs_org_ids
559
+ },
560
+ unverified_inheritance_from_orgs={
561
+ org_ref_lookup.get(
562
+ source_org_id, OrgRef(org_id=source_org_id, env_name="unknown")
563
+ )
564
+ for source_org_id in unverified_inheritance_from_orgs_org_ids
565
+ },
566
+ )
567
+
568
+
569
+ #
570
+ # Feedback mechanism
571
+ #
572
+
573
+
574
+ def _signal_validation_issues_for_org(
575
+ ocm_api: OCMBaseClient,
576
+ org_upgrade_spec: OrganizationUpgradeSpec,
577
+ ) -> None:
578
+ """
579
+ Signal the validation errors of an organization to the users.
580
+ Right now it uses OCM service logs, but it could be extended to use
581
+ other mechanisms like slack etc.
582
+ """
583
+ org_id = org_upgrade_spec.org.org_id
584
+ ocm_env_name = org_upgrade_spec.org.environment.name
585
+
586
+ if org_upgrade_spec.cluster_errors:
587
+ logging.warning(
588
+ f"Cluster config errors found in {ocm_env_name} org {org_id}: "
589
+ f"{org_upgrade_spec.cluster_errors}"
590
+ )
591
+ for cluster_error in org_upgrade_spec.cluster_errors:
592
+ _expose_cluster_validation_errors_as_service_log(
593
+ ocm_api=ocm_api,
594
+ cluster_uuid=cluster_error.cluster_uuid,
595
+ errors=cluster_error.messages,
596
+ )
597
+
598
+ if org_upgrade_spec.organization_errors:
599
+ logging.warning(
600
+ f"Organization config errors found in {ocm_env_name} org {org_id}: "
601
+ f"{org_upgrade_spec.organization_errors}"
602
+ )
603
+ org_error_msg = "\n".join(
604
+ o.message for o in org_upgrade_spec.organization_errors
605
+ )
606
+ for cluster in org_upgrade_spec.specs:
607
+ create_service_log(
608
+ ocm_api=ocm_api,
609
+ service_log=OCMClusterServiceLogCreateModel(
610
+ cluster_uuid=cluster.cluster_uuid,
611
+ severity=OCMServiceLogSeverity.Warning,
612
+ summary="AUS configuration error on organization",
613
+ description=org_error_msg,
614
+ service_name=QONTRACT_INTEGRATION,
615
+ ),
616
+ dedup_interval=timedelta(days=1),
617
+ )
618
+
619
+
620
+ def _expose_cluster_validation_errors_as_service_log(
621
+ ocm_api: OCMBaseClient, cluster_uuid: str, errors: list[str]
622
+ ) -> None:
623
+ """
624
+ Highlight cluster upgrade policy validation errors to the cluster
625
+ owners via OCM service logs.
626
+ """
627
+ description = "\n".join([f"- {e}" for e in errors])
628
+ create_service_log(
629
+ ocm_api=ocm_api,
630
+ service_log=OCMClusterServiceLogCreateModel(
631
+ cluster_uuid=cluster_uuid,
632
+ severity=OCMServiceLogSeverity.Warning,
633
+ summary="Cluster upgrade policy validation errors",
634
+ description=description,
635
+ service_name=QONTRACT_INTEGRATION,
636
+ ),
637
+ dedup_interval=timedelta(days=1),
638
+ )