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
@@ -0,0 +1,123 @@
1
+ from collections.abc import (
2
+ Callable,
3
+ Generator,
4
+ MutableMapping,
5
+ )
6
+ from typing import Any
7
+
8
+ from croniter import croniter
9
+ from pydantic import (
10
+ BaseModel,
11
+ ValidationError,
12
+ )
13
+ from pydantic import errors as pydantic_errors
14
+ from pydantic.fields import ModelField
15
+
16
+ DEFAULT_STRING = "I was too lazy to define a string here"
17
+ DEFAULT_INT = 42
18
+
19
+
20
+ def data_default_none(
21
+ klass: type[BaseModel], data: MutableMapping[str, Any], use_defaults: bool = True
22
+ ) -> MutableMapping[str, Any]:
23
+ """Set default values to None for required but optional fields."""
24
+ for field in klass.__fields__.values():
25
+ if not field.required:
26
+ continue
27
+
28
+ if field.alias not in data:
29
+ # Settings defaults
30
+ if field.allow_none:
31
+ data[field.alias] = None
32
+ elif not use_defaults:
33
+ raise ValueError(f"Field {field.alias} is required but not set.")
34
+ elif isinstance(field.type_, type) and issubclass(field.type_, str):
35
+ data[field.alias] = DEFAULT_STRING
36
+ elif isinstance(field.type_, type) and issubclass(field.type_, bool):
37
+ data[field.alias] = False
38
+ elif isinstance(field.type_, type) and issubclass(field.type_, int):
39
+ data[field.alias] = DEFAULT_INT
40
+ elif isinstance(field.type_, type) and issubclass(field.type_, BaseModel):
41
+ if isinstance(data[field.alias], dict):
42
+ data[field.alias] = data_default_none(field.type_, data[field.alias])
43
+ if isinstance(data[field.alias], list):
44
+ data[field.alias] = [
45
+ data_default_none(field.type_, item)
46
+ for item in data[field.alias]
47
+ if isinstance(item, dict)
48
+ ]
49
+ elif field.sub_fields:
50
+ if all(
51
+ isinstance(sub_field.type_, type)
52
+ and issubclass(sub_field.type_, BaseModel)
53
+ for sub_field in field.sub_fields
54
+ ):
55
+ # Union[ClassA, ClassB] field
56
+ for sub_field in field.sub_fields:
57
+ if isinstance(data[field.alias], dict):
58
+ try:
59
+ d = dict(data[field.alias])
60
+ d.update(data_default_none(sub_field.type_, d))
61
+ # Lets confirm we found a matching union class
62
+ sub_field.type_(**d)
63
+ data[field.alias] = d
64
+ break
65
+ except ValidationError:
66
+ continue
67
+ elif isinstance(data[field.alias], list) and len(field.sub_fields) == 1:
68
+ # list[Union[ClassA, ClassB]] field
69
+ for sub_data in data[field.alias]:
70
+ for sub_field in field.sub_fields[0].sub_fields or []:
71
+ try:
72
+ d = dict(sub_data)
73
+ d.update(data_default_none(sub_field.type_, d))
74
+ # Lets confirm we found a matching union class
75
+ sub_field.type_(**d)
76
+ sub_data.update(d)
77
+ break
78
+ except ValidationError:
79
+ continue
80
+
81
+ return data
82
+
83
+
84
+ class CSV(list[str]):
85
+ """
86
+ A pydantic custom type that converts a CSV into a list of strings. It
87
+ also supports basic validation of length constraints.
88
+ """
89
+
90
+ @classmethod
91
+ def __get_validators__(cls) -> Generator[Callable, None, None]: # noqa: PLW3201
92
+ yield cls.validate
93
+ yield cls.length_validator
94
+
95
+ @classmethod
96
+ def validate(cls, value: str) -> list[str]:
97
+ items = [] if not value else value.split(",")
98
+ return items
99
+
100
+ @classmethod
101
+ def length_validator(
102
+ cls, v: "list[str]", values: dict, field: ModelField
103
+ ) -> "list[str]":
104
+ min_items = field.field_info.extra.get("csv_min_items")
105
+ max_items = field.field_info.extra.get("csv_max_items")
106
+
107
+ v_len = len(v)
108
+ if min_items is not None and v_len < min_items:
109
+ raise pydantic_errors.ListMinLengthError(limit_value=min_items)
110
+ if max_items is not None and v_len > max_items:
111
+ raise pydantic_errors.ListMaxLengthError(limit_value=max_items)
112
+ return v
113
+
114
+
115
+ def cron_validator(value: str) -> str:
116
+ """
117
+ A pydantic validator for a cron expression.
118
+ """
119
+ try:
120
+ croniter(value)
121
+ return value
122
+ except ValueError as e:
123
+ raise ValueError(f"Invalid cron expression: {e}") from None
@@ -0,0 +1,198 @@
1
+ # Merge Requests
2
+
3
+ Module responsible for abstracting a Gitlab Merge Request.
4
+
5
+ ## Creating New MergeRequest Classes
6
+
7
+ Each type of merge request requires a class that inherits
8
+ from reconcile.utils.mr.base.MergeRequestBase.
9
+
10
+ That class has to comply with the specification below.
11
+
12
+ ### Class Name
13
+
14
+ The class name is given by the class variable `name`. That name will be
15
+ used all around, the most important place being the SQS Message parameter
16
+ `pr_type`, used later to create an instance of the same class.
17
+
18
+ While the name can be anything it is mandatory that it is defined.
19
+
20
+ ### Class Initialization
21
+
22
+ The `__init__` method has to call `super().__init__()` right after the minimum
23
+ parameters initialization. That is required to compose the SQS Message that
24
+ will later be used to create a new instance of the same class.
25
+
26
+ ### Class Methods
27
+
28
+ The minimum methods that have to be defined are:
29
+
30
+ * `title`: a property that is used to give the Gitlab Merge Request a title.
31
+ It can also be used for building commit messages or as content to committed
32
+ files.
33
+ * `description`: a description for the Merge Request.
34
+ * `process`: this method is called when submitting the Merge Request to gitlab.
35
+ it's the place for the merge request changes, like creating, updating and
36
+ deleting files. The `process` method is called after the local branch is
37
+ created and right after it the `gitlab_cli.project.mergerequests.create()`
38
+ is called.
39
+
40
+ ### Example
41
+
42
+ This is an example of a minimum implementation for a new MergeRequest class:
43
+
44
+ ```python
45
+ from reconcile.utils.mr.base import MergeRequestBase
46
+
47
+
48
+ class CreateDeleteUser(MergeRequestBase):
49
+
50
+ name = 'create_delete_user_mr'
51
+
52
+ def __init__(self, username, paths):
53
+ self.username = username
54
+ self.paths = paths
55
+
56
+ # Called right after the minimum parameters to recreate
57
+ # an instance with the same data. This is important for
58
+ # building up the SQS message payload.
59
+ super().__init__()
60
+
61
+ @property
62
+ def title(self) -> str:
63
+ return f'[{self.name}] delete user {self.username}'
64
+
65
+ @property
66
+ def description(self) -> str:
67
+ return f'delete user {self.username}'
68
+
69
+ def process(self, gitlab_cli):
70
+ for path in self.paths:
71
+ gitlab_cli.delete_file(branch_name=self.branch,
72
+ file_path=path,
73
+ commit_message=self.title)
74
+ ```
75
+
76
+ ## Sending MRs to SQS
77
+
78
+ To send a Merge Request to SQS, create the corresponding MergeRequest object:
79
+
80
+ ```python
81
+ from reconcile.utils.mr import CreateAppInterfaceNotificator
82
+
83
+
84
+ notification = {
85
+ 'notification_type': 'Outage',
86
+ 'description': 'The AppSRE team is currently investigating an outage',
87
+ 'short_description': 'Short Description',
88
+ }
89
+
90
+ merge_request = CreateAppInterfaceNotificator(notification=notification)
91
+
92
+ ```
93
+
94
+ then create the SQS Client instance:
95
+
96
+ ```python
97
+ from reconcile import queries
98
+
99
+ from reconcile.utils.sqs_gateway import SQSGateway
100
+ from reconcile.utils.secret_reader import SecretReader
101
+
102
+
103
+ accounts = queries.get_queue_aws_accounts()
104
+ secretReader = SecretReader(queries.get_secret_reader_settings())
105
+ sqs_cli = SQSGateway(accounts, secret_reader=secret_reader)
106
+ ```
107
+
108
+ and then submit the merge request to the SQS:
109
+
110
+ ```python
111
+ merge_request.submit_to_sqs(sqs_cli=sqs_cli)
112
+ ```
113
+
114
+ ## Sending MRs to Gitlab
115
+
116
+ To get the message from SQS and use it for sending a Merge Request to gitlab,
117
+ first get the SQS messages:
118
+
119
+
120
+ ```python
121
+ from reconcile import queries
122
+
123
+ from reconcile.utils.sqs_gateway import SQSGateway
124
+ from reconcile.utils.secret_reader import SecretReader
125
+
126
+
127
+ accounts = queries.get_queue_aws_accounts()
128
+ settings = queries.get_app_interface_settings()
129
+
130
+ secretReader = SecretReader(queries.get_secret_reader_settings())
131
+ sqs_cli = SQSGateway(accounts, secret_reader=secret_reader)
132
+ messages = sqs_cli.receive_messages()
133
+ ```
134
+
135
+ then create the Gitlab client instance:
136
+
137
+ ```python
138
+ from reconcile.utils.gitlab_api import GitLabApi
139
+
140
+ instance = queries.get_gitlab_instance()
141
+ saas_files = queries.get_saas_files_minimal()
142
+ gitlab_cli = GitLabApi(instance, project_id=gitlab_project_id,
143
+ settings=settings)
144
+ ```
145
+
146
+ and then loop the messages, creating the MergeRequest objects and submitting
147
+ the merge requests:
148
+
149
+ ```python
150
+ from reconcile.utils.mr import init_from_sqs_message
151
+
152
+ for message in messages:
153
+ receipt_handle, body = message[0], message[1]
154
+ merge_request = init_from_sqs_message(body)
155
+ merge_request.submit_to_gitlab(gitlab_cli=gitlab_cli)
156
+ sqs_cli.delete_message(receipt_handle)
157
+ ```
158
+
159
+ ## Using the MR Module for Qontract-reconcile Integrations
160
+
161
+ A given integration might be executed in different environments, like:
162
+
163
+ * Developer local machine.
164
+ * OpenShift cluster outside the VPN.
165
+ * OpenShift cluster inside the VPN.
166
+ * Jenkins periodic job.
167
+
168
+ Because we don't want the integrations to care if they are running inside or
169
+ outside the VPN, we use the `reconcile.mr_client_gateway.init()` to get the
170
+ on of SQS or GitLab client, according to the App Interface settings. Example:
171
+
172
+ ```python
173
+ from reconcile import mr_client_gateway
174
+ from reconcile.utils.mr import CreateDeleteAwsAccessKey
175
+
176
+
177
+ def run(dry_run, gitlab_project_id):
178
+ ...
179
+ mr = CreateDeleteAwsAccessKey(...)
180
+ with mr_client_gateway.init(gitlab_project_id=gitlab_project_id) as mr_cli:
181
+ mr.submit(cli=mr_cli)
182
+ ```
183
+
184
+ If we want to override what's set in App Interface and get a specific client,
185
+ say `gitlab`, we would:
186
+
187
+ ```python
188
+ from reconcile import mr_client_gateway
189
+ from reconcile.utils.mr import CreateDeleteAwsAccessKey
190
+
191
+
192
+ def run(dry_run, gitlab_project_id):
193
+ ...
194
+ mr = CreateDeleteAwsAccessKey(...)
195
+ with mr_client_gateway.init(sqs_or_gitlab='gitlab',
196
+ gitlab_project_id=gitlab_project_id) as mr_cli:
197
+ mr.submit(cli=mr_cli)
198
+ ```
@@ -1,5 +1,4 @@
1
1
  from reconcile.utils.mr.app_interface_reporter import CreateAppInterfaceReporter
2
- from reconcile.utils.mr.auto_promoter import AutoPromoter
3
2
  from reconcile.utils.mr.aws_access import CreateDeleteAwsAccessKey
4
3
  from reconcile.utils.mr.base import (
5
4
  MergeRequestBase,
@@ -13,24 +12,29 @@ from reconcile.utils.mr.ocm_update_recommended_version import (
13
12
  from reconcile.utils.mr.ocm_upgrade_scheduler_org_updates import (
14
13
  CreateOCMUpgradeSchedulerOrgUpdates,
15
14
  )
15
+ from reconcile.utils.mr.promote_qontract import (
16
+ PromoteQontractReconcileCommercial,
17
+ PromoteQontractSchemas,
18
+ )
16
19
  from reconcile.utils.mr.user_maintenance import (
17
20
  CreateDeleteUserAppInterface,
18
21
  CreateDeleteUserInfra,
19
22
  )
20
23
 
21
24
  __all__ = [
22
- "init_from_sqs_message",
23
- "UnknownMergeRequestType",
24
- "MergeRequestProcessingError",
25
+ "CreateAppInterfaceNotificator",
25
26
  "CreateAppInterfaceReporter",
26
- "CreateDeleteAwsAccessKey",
27
27
  "CreateClustersUpdates",
28
- "CreateOCMUpgradeSchedulerOrgUpdates",
29
- "CreateOCMUpdateRecommendedVersion",
30
- "CreateAppInterfaceNotificator",
28
+ "CreateDeleteAwsAccessKey",
31
29
  "CreateDeleteUserAppInterface",
32
30
  "CreateDeleteUserInfra",
33
- "AutoPromoter",
31
+ "CreateOCMUpdateRecommendedVersion",
32
+ "CreateOCMUpgradeSchedulerOrgUpdates",
33
+ "MergeRequestProcessingError",
34
+ "PromoteQontractReconcileCommercial",
35
+ "PromoteQontractSchemas",
36
+ "UnknownMergeRequestType",
37
+ "init_from_sqs_message",
34
38
  ]
35
39
 
36
40
 
@@ -40,7 +44,7 @@ class UnknownMergeRequestType(Exception):
40
44
  """
41
45
 
42
46
 
43
- def init_from_sqs_message(message):
47
+ def init_from_sqs_message(message) -> MergeRequestBase:
44
48
  # First, let's find the classes that are inheriting from
45
49
  # MergeRequestBase and create a map where the class.name is
46
50
  # the key and the class itself is the value.
@@ -3,6 +3,7 @@ from pathlib import Path
3
3
 
4
4
  from ruamel.yaml.scalarstring import PreservedScalarString as pss
5
5
 
6
+ from reconcile.utils.gitlab_api import GitLabApi
6
7
  from reconcile.utils.mr.base import (
7
8
  MergeRequestBase,
8
9
  app_interface_email,
@@ -11,7 +12,6 @@ from reconcile.utils.mr.labels import AUTO_MERGE
11
12
 
12
13
 
13
14
  class CreateAppInterfaceReporter(MergeRequestBase):
14
-
15
15
  name = "create_app_interface_reporter_mr"
16
16
 
17
17
  def __init__(self, reports, email_body, reports_path):
@@ -35,7 +35,7 @@ class CreateAppInterfaceReporter(MergeRequestBase):
35
35
  def description(self) -> str:
36
36
  return f"reports for {self.isodate}"
37
37
 
38
- def process(self, gitlab_cli):
38
+ def process(self, gitlab_cli: GitLabApi) -> None:
39
39
  actions = [
40
40
  {
41
41
  "action": "create",
@@ -5,6 +5,7 @@ from ruamel import yaml
5
5
  from ruamel.yaml.scalarstring import PreservedScalarString as pss
6
6
 
7
7
  from reconcile.utils.constants import PROJ_ROOT
8
+ from reconcile.utils.gitlab_api import GitLabApi
8
9
  from reconcile.utils.mr.base import (
9
10
  MergeRequestBase,
10
11
  app_interface_email,
@@ -15,7 +16,6 @@ BODY_TEMPLATE = PROJ_ROOT / "templates" / "aws_access_key_email.j2"
15
16
 
16
17
 
17
18
  class CreateDeleteAwsAccessKey(MergeRequestBase):
18
-
19
19
  name = "create_delete_aws_access_key_mr"
20
20
 
21
21
  def __init__(self, account, path, key):
@@ -35,10 +35,10 @@ class CreateDeleteAwsAccessKey(MergeRequestBase):
35
35
  def description(self) -> str:
36
36
  return f"delete {self.account} access key {self.key}"
37
37
 
38
- def process(self, gitlab_cli):
38
+ def process(self, gitlab_cli: GitLabApi) -> None:
39
39
  # add key to deleteKeys list to be picked up by aws-iam-keys
40
40
  raw_file = gitlab_cli.project.files.get(
41
- file_path=self.path, ref=self.main_branch
41
+ file_path=self.path, ref=gitlab_cli.main_branch
42
42
  )
43
43
  content = yaml.load(raw_file.decode(), Loader=yaml.RoundTripLoader)
44
44
 
@@ -57,7 +57,7 @@ class CreateDeleteAwsAccessKey(MergeRequestBase):
57
57
  )
58
58
 
59
59
  # add a new email to be picked up by email-sender
60
- with open(BODY_TEMPLATE) as file_obj:
60
+ with open(BODY_TEMPLATE, encoding="locale") as file_obj:
61
61
  body_template = Template(
62
62
  file_obj.read(), keep_trailing_newline=True, trim_blocks=True
63
63
  )
@@ -1,18 +1,18 @@
1
1
  import json
2
2
  import logging
3
3
  from abc import (
4
- ABCMeta,
4
+ ABC,
5
5
  abstractmethod,
6
6
  )
7
- from typing import (
8
- Optional,
9
- Union,
10
- )
7
+ from collections.abc import Iterable
8
+ from typing import Any
11
9
  from uuid import uuid4
12
10
 
13
11
  from gitlab.exceptions import GitlabError
14
12
  from jinja2 import Template
15
13
 
14
+ from reconcile import typed_queries
15
+ from reconcile.gql_definitions.fragments.user import User
16
16
  from reconcile.utils.constants import PROJ_ROOT
17
17
  from reconcile.utils.gitlab_api import GitLabApi
18
18
  from reconcile.utils.mr.labels import DO_NOT_MERGE_HOLD
@@ -35,10 +35,10 @@ class MergeRequestProcessingError(Exception):
35
35
  """
36
36
 
37
37
 
38
- MRClient = Union[GitLabApi, SQSGateway]
38
+ MRClient = GitLabApi | SQSGateway
39
39
 
40
40
 
41
- class MergeRequestBase(metaclass=ABCMeta):
41
+ class MergeRequestBase(ABC):
42
42
  """
43
43
  Base abstract class for all merge request types.
44
44
  """
@@ -52,19 +52,17 @@ class MergeRequestBase(metaclass=ABCMeta):
52
52
  # of the child class.
53
53
  self.sqs_msg_data = {**self.__dict__}
54
54
 
55
- self.gitlab_cli = None
56
55
  self.labels = [DO_NOT_MERGE_HOLD]
57
56
 
58
57
  random_id = str(uuid4())[:6]
59
58
  self.branch = f"{self.name}-{random_id}"
60
59
  self.branch_created = False
61
60
 
62
- self.main_branch = "master"
63
61
  self.remove_source_branch = True
64
62
 
65
63
  self.cancelled = False
66
64
 
67
- def cancel(self, message):
65
+ def cancel(self, message: str) -> None:
68
66
  self.cancelled = True
69
67
  raise CancelMergeRequest(
70
68
  f"{self.name} MR canceled for "
@@ -93,7 +91,7 @@ class MergeRequestBase(metaclass=ABCMeta):
93
91
  """
94
92
 
95
93
  @abstractmethod
96
- def process(self, gitlab_cli):
94
+ def process(self, gitlab_cli: GitLabApi) -> None:
97
95
  """
98
96
  Called by `submit_to_gitlab`, this method is the place for
99
97
  user-defined steps to create the commits of a merge request.
@@ -103,7 +101,7 @@ class MergeRequestBase(metaclass=ABCMeta):
103
101
  """
104
102
 
105
103
  @property
106
- def sqs_data(self):
104
+ def sqs_data(self) -> dict[str, Any]:
107
105
  """
108
106
  The SQS Message payload (MessageBody) generated out of
109
107
  the Merge Request class instance.
@@ -113,7 +111,27 @@ class MergeRequestBase(metaclass=ABCMeta):
113
111
  **self.sqs_msg_data,
114
112
  }
115
113
 
116
- def submit_to_sqs(self, sqs_cli) -> None:
114
+ def infer_author(
115
+ self, author_email: str | None, all_users: Iterable[User] | None = None
116
+ ) -> str | None:
117
+ if not author_email:
118
+ return None
119
+ if not all_users:
120
+ return None
121
+
122
+ username = author_email.split("@")[0]
123
+ users = None
124
+ if author_email.endswith(typed_queries.smtp.settings().mail_address):
125
+ users = [u for u in all_users if username == u.org_username]
126
+ elif author_email.endswith("users.noreply.github.com"):
127
+ users = [u for u in all_users if username == u.github_username]
128
+
129
+ if users:
130
+ return users[0].org_username
131
+
132
+ return None
133
+
134
+ def submit_to_sqs(self, sqs_cli: SQSGateway) -> None:
117
135
  """
118
136
  Sends the MR message to SQS.
119
137
 
@@ -122,21 +140,20 @@ class MergeRequestBase(metaclass=ABCMeta):
122
140
  """
123
141
  sqs_cli.send_message(self.sqs_data)
124
142
 
125
- @property
126
- def gitlab_data(self):
143
+ def gitlab_data(self, target_branch: str) -> dict[str, Any]:
127
144
  """
128
145
  The Gitlab payload for creating the Merge Request.
129
146
  """
130
147
  return {
131
148
  "source_branch": self.branch,
132
- "target_branch": self.main_branch,
149
+ "target_branch": target_branch,
133
150
  "title": self.title,
134
151
  "description": self.description,
135
152
  "remove_source_branch": self.remove_source_branch,
136
153
  "labels": self.labels,
137
154
  }
138
155
 
139
- def submit_to_gitlab(self, gitlab_cli):
156
+ def submit_to_gitlab(self, gitlab_cli: GitLabApi) -> Any:
140
157
  """
141
158
  Sends the MR to Gitlab.
142
159
 
@@ -163,11 +180,13 @@ class MergeRequestBase(metaclass=ABCMeta):
163
180
  # Avoiding empty MRs
164
181
  if not self.diffs(gitlab_cli):
165
182
  self.cancel(
166
- f"No changes when compared to {self.main_branch}. "
183
+ f"No changes when compared to {gitlab_cli.main_branch}. "
167
184
  "Aborting MR creation."
168
185
  )
169
186
 
170
- return gitlab_cli.project.mergerequests.create(self.gitlab_data)
187
+ return gitlab_cli.project.mergerequests.create(
188
+ self.gitlab_data(target_branch=gitlab_cli.main_branch)
189
+ )
171
190
  except CancelMergeRequest as mr_cancel:
172
191
  # cancellation is a valid behaviour. it indicates, that the
173
192
  # operation is not required, therefore we will not signal
@@ -187,14 +206,14 @@ class MergeRequestBase(metaclass=ABCMeta):
187
206
  f"Reason: {err}"
188
207
  ) from err
189
208
 
190
- def ensure_tmp_branch_exists(self, gitlab_cli):
209
+ def ensure_tmp_branch_exists(self, gitlab_cli: GitLabApi) -> None:
191
210
  if not self.branch_created:
192
211
  gitlab_cli.create_branch(
193
- new_branch=self.branch, source_branch=self.main_branch
212
+ new_branch=self.branch, source_branch=gitlab_cli.main_branch
194
213
  )
195
214
  self.branch_created = True
196
215
 
197
- def delete_tmp_branch(self, gitlab_cli):
216
+ def delete_tmp_branch(self, gitlab_cli: GitLabApi) -> None:
198
217
  if self.branch_created:
199
218
  try:
200
219
  gitlab_cli.delete_branch(branch=self.branch)
@@ -206,17 +225,18 @@ class MergeRequestBase(metaclass=ABCMeta):
206
225
  f"Failed to delete branch {self.branch}. " f"Reason: {gitlab_error}"
207
226
  )
208
227
 
209
- def diffs(self, gitlab_cli):
228
+ def diffs(self, gitlab_cli: GitLabApi) -> Any:
210
229
  return gitlab_cli.project.repository_compare(
211
- from_=self.main_branch, to=self.branch
230
+ from_=gitlab_cli.main_branch, to=self.branch
212
231
  )["diffs"]
213
232
 
214
- def submit(self, cli: MRClient):
233
+ def submit(self, cli: MRClient) -> Any | None:
215
234
  if isinstance(cli, GitLabApi):
216
235
  return self.submit_to_gitlab(gitlab_cli=cli)
217
236
 
218
237
  if isinstance(cli, SQSGateway):
219
- return self.submit_to_sqs(sqs_cli=cli)
238
+ self.submit_to_sqs(sqs_cli=cli)
239
+ return None
220
240
 
221
241
  raise AttributeError(f"client {cli} not supported")
222
242
 
@@ -225,13 +245,13 @@ def app_interface_email(
225
245
  name: str,
226
246
  subject: str,
227
247
  body: str,
228
- users: Optional[list[str]] = None,
229
- aliases: Optional[list[str]] = None,
230
- aws_accounts: Optional[list[str]] = None,
231
- apps: Optional[list[str]] = None,
248
+ users: list[str] | None = None,
249
+ aliases: list[str] | None = None,
250
+ aws_accounts: list[str] | None = None,
251
+ apps: list[str] | None = None,
232
252
  ) -> str:
233
253
  """Render app-interface-email template."""
234
- with open(EMAIL_TEMPLATE) as file_obj:
254
+ with open(EMAIL_TEMPLATE, encoding="locale") as file_obj:
235
255
  email_template = Template(
236
256
  file_obj.read(), keep_trailing_newline=True, trim_blocks=True
237
257
  )
@@ -3,14 +3,16 @@ from io import StringIO
3
3
  from ruamel.yaml import YAML
4
4
 
5
5
  from reconcile.change_owners.decision import DecisionCommand
6
+ from reconcile.utils.gitlab_api import GitLabApi
6
7
  from reconcile.utils.mr.base import MergeRequestBase
7
8
 
8
9
  yaml = YAML()
9
- yaml.explicit_start = True # type: ignore
10
+ yaml.explicit_start = True
11
+ # Lets prevent line wraps
12
+ yaml.width = 4096
10
13
 
11
14
 
12
15
  class CreateClustersUpdates(MergeRequestBase):
13
-
14
16
  name = "create_clusters_updates_mr"
15
17
 
16
18
  def __init__(self, clusters_updates):
@@ -28,7 +30,7 @@ class CreateClustersUpdates(MergeRequestBase):
28
30
  def description(self) -> str:
29
31
  return DecisionCommand.APPROVED.value
30
32
 
31
- def process(self, gitlab_cli):
33
+ def process(self, gitlab_cli: GitLabApi):
32
34
  changes = False
33
35
  for cluster_name, cluster_updates in self.clusters_updates.items():
34
36
  if not cluster_updates:
@@ -36,7 +38,7 @@ class CreateClustersUpdates(MergeRequestBase):
36
38
 
37
39
  cluster_path = cluster_updates.pop("path")
38
40
  raw_file = gitlab_cli.project.files.get(
39
- file_path=cluster_path, ref=self.main_branch
41
+ file_path=cluster_path, ref=gitlab_cli.main_branch
40
42
  )
41
43
  content = yaml.load(raw_file.decode())
42
44
  if "spec" not in content:
@@ -55,15 +57,16 @@ class CreateClustersUpdates(MergeRequestBase):
55
57
  # content.update(cluster_updates) :(
56
58
  content.update(cluster_updates["root"])
57
59
 
58
- new_content = StringIO()
59
- yaml.dump(content, new_content)
60
+ with StringIO() as stream:
61
+ yaml.dump(content, stream)
62
+ new_content = stream.getvalue()
60
63
 
61
64
  msg = f"update cluster {cluster_name} spec fields"
62
65
  gitlab_cli.update_file(
63
66
  branch_name=self.branch,
64
67
  file_path=cluster_path,
65
68
  commit_message=msg,
66
- content=new_content.getvalue(),
69
+ content=new_content,
67
70
  )
68
71
 
69
72
  if not changes: