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,196 @@
1
+ import logging
2
+ from collections import defaultdict
3
+ from datetime import timedelta
4
+
5
+ from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment
6
+ from reconcile.oum.base import OCMUserManagementIntegration
7
+ from reconcile.oum.labelset import build_cluster_config_from_labels
8
+ from reconcile.oum.models import (
9
+ ClusterError,
10
+ ClusterUserManagementConfiguration,
11
+ ClusterUserManagementSpec,
12
+ OrganizationUserManagementConfiguration,
13
+ )
14
+ from reconcile.utils.ocm.base import (
15
+ OCMClusterServiceLogCreateModel,
16
+ OCMServiceLogSeverity,
17
+ )
18
+ from reconcile.utils.ocm.clusters import (
19
+ ClusterDetails,
20
+ discover_clusters_by_labels,
21
+ )
22
+ from reconcile.utils.ocm.labels import build_container_for_prefix
23
+ from reconcile.utils.ocm.search_filters import Filter
24
+ from reconcile.utils.ocm.service_log import create_service_log
25
+ from reconcile.utils.ocm.sre_capability_labels import sre_capability_label_key
26
+ from reconcile.utils.ocm_base_client import (
27
+ OCMBaseClient,
28
+ init_ocm_base_client,
29
+ )
30
+
31
+
32
+ class OCMStandaloneUserManagementIntegration(OCMUserManagementIntegration):
33
+ @property
34
+ def name(self) -> str:
35
+ return "ocm-standalone-user-management"
36
+
37
+ def get_user_mgmt_config_for_ocm_env(
38
+ self, ocm_env: OCMEnvironment, org_ids: set[str] | None
39
+ ) -> dict[str, OrganizationUserManagementConfiguration]:
40
+ ocm_api = init_ocm_base_client(ocm_env, self.secret_reader)
41
+ clusters_by_org = discover_clusters(
42
+ ocm_api=ocm_api,
43
+ org_ids=org_ids,
44
+ )
45
+ configs: dict[str, OrganizationUserManagementConfiguration] = {}
46
+ for org_id, org_clusters in clusters_by_org.items():
47
+ configs[org_id] = build_user_management_configurations(
48
+ org_id=org_id,
49
+ clusters=org_clusters,
50
+ providers=self.group_member_provider_ids,
51
+ )
52
+ return configs
53
+
54
+ def signal_cluster_reconcile_success(
55
+ self,
56
+ dry_run: bool,
57
+ ocm_api: OCMBaseClient,
58
+ spec: ClusterUserManagementSpec,
59
+ message: str,
60
+ ) -> None:
61
+ logging.info(message)
62
+ if dry_run:
63
+ return
64
+ create_service_log(
65
+ ocm_api=ocm_api,
66
+ service_log=OCMClusterServiceLogCreateModel(
67
+ cluster_uuid=spec.cluster.ocm_cluster.external_id,
68
+ severity=OCMServiceLogSeverity.Info,
69
+ summary="Reconciled cluster groups",
70
+ description=message,
71
+ service_name=self.name,
72
+ ),
73
+ )
74
+
75
+ def signal_cluster_validation_error(
76
+ self,
77
+ dry_run: bool,
78
+ ocm_api: OCMBaseClient,
79
+ spec: ClusterUserManagementSpec,
80
+ error: Exception,
81
+ ) -> None:
82
+ """
83
+ The standalone user management capability will not fail on a configuration
84
+ validation issue. If issues should be noticed by an SRE team, alerts based on
85
+ the `oum_organization_validation_errors` metric in the `reconcile.oum.metrics`
86
+ module should be set up.
87
+ """
88
+ logging.warning(
89
+ "Failed to reconcile cluster user group configuration in "
90
+ f"OCM organization {spec.cluster.organization_id}",
91
+ exc_info=error,
92
+ )
93
+ if dry_run:
94
+ return
95
+ create_service_log(
96
+ ocm_api=ocm_api,
97
+ service_log=OCMClusterServiceLogCreateModel(
98
+ cluster_uuid=spec.cluster.ocm_cluster.external_id,
99
+ severity=OCMServiceLogSeverity.Error,
100
+ summary="Failed to reconcile cluster user group configuration",
101
+ description=str(error),
102
+ service_name=self.name,
103
+ ),
104
+ dedup_interval=timedelta(days=2),
105
+ )
106
+
107
+ def signal_cluster_reconcile_error(
108
+ self,
109
+ dry_run: bool,
110
+ ocm_api: OCMBaseClient,
111
+ spec: ClusterUserManagementSpec,
112
+ error: Exception,
113
+ ) -> None:
114
+ """
115
+ The standalone user management capability will not fail on a cluster
116
+ reconciliation issue. If issues should be noticed by an SRE team, alerts based on
117
+ the `oum_organization_reconcile_errors` metric in the `reconcile.oum.metrics`
118
+ module should be set up.
119
+
120
+ The user is not notified via service logs because such reconcile issues are not
121
+ actionable to them.
122
+ """
123
+ logging.warning(
124
+ "Failed to reconcile cluster user group configuration on "
125
+ f"cluster {spec.cluster.ocm_cluster.name} (id={spec.cluster.ocm_cluster.id}) "
126
+ f"in the OCM organization {spec.cluster.organization_id}",
127
+ exc_info=error,
128
+ )
129
+
130
+
131
+ def user_mgmt_label_key(config_atom: str) -> str:
132
+ """
133
+ Generates label keys for the user management authz capability, compliant with the naming
134
+ scheme defined in https://service.pages.redhat.com/dev-guidelines/docs/sre-capabilities/framework/ocm-labels/
135
+ """
136
+ return sre_capability_label_key("user-mgmt", config_atom)
137
+
138
+
139
+ def discover_clusters(
140
+ ocm_api: OCMBaseClient,
141
+ org_ids: set[str] | None = None,
142
+ ) -> dict[str, list[ClusterDetails]]:
143
+ """
144
+ Discover all clusters with user management enabled on their subscription
145
+ or their organization. Return the discovered clusters grouped by OCM organization ID.
146
+
147
+ If `org_ids` is provided, only clusters from the specified organizations will be returned.
148
+ """
149
+ clusters = discover_clusters_by_labels(
150
+ ocm_api=ocm_api,
151
+ label_filter=Filter().like("key", user_mgmt_label_key("%")),
152
+ )
153
+
154
+ # group by org ID
155
+ # optionally also filter on org IDs
156
+ clusters_by_org: dict[str, list[ClusterDetails]] = defaultdict(list)
157
+ for c in clusters:
158
+ passed_ocm_filters = org_ids is None or c.organization_id in org_ids
159
+ if passed_ocm_filters:
160
+ clusters_by_org[c.organization_id].append(c)
161
+
162
+ return clusters_by_org
163
+
164
+
165
+ def build_user_management_configurations(
166
+ org_id: str,
167
+ clusters: list[ClusterDetails],
168
+ providers: set[str],
169
+ ) -> OrganizationUserManagementConfiguration:
170
+ """
171
+ Extracts the user management configuration from the cluster labels.
172
+ """
173
+ org_config = OrganizationUserManagementConfiguration(org_id=org_id)
174
+ for c in clusters:
175
+ cluster_config = ClusterUserManagementConfiguration(cluster=c)
176
+ org_config.cluster_configs.append(cluster_config)
177
+ for p in providers:
178
+ provider_org_labels = build_container_for_prefix(
179
+ c.organization_labels, user_mgmt_label_key(f"{p}."), True
180
+ )
181
+ provider_subs_labels = build_container_for_prefix(
182
+ c.subscription_labels, user_mgmt_label_key(f"{p}."), True
183
+ )
184
+ if provider_org_labels or provider_subs_labels:
185
+ try:
186
+ role_groups = build_cluster_config_from_labels(
187
+ provider=p,
188
+ org_labels=provider_org_labels,
189
+ subscription_labels=provider_subs_labels,
190
+ )
191
+ for role_id, group_refs in role_groups.items():
192
+ cluster_config.roles[role_id].extend(group_refs)
193
+
194
+ except Exception as e:
195
+ cluster_config.errors.append(ClusterError(message=str(e)))
196
+ return org_config
@@ -1,16 +1,15 @@
1
1
  import json
2
2
  import logging
3
3
  import sys
4
+ from collections import defaultdict
4
5
  from collections.abc import (
5
6
  Iterable,
6
7
  Mapping,
7
8
  )
8
- from typing import (
9
- Any,
10
- Optional,
11
- )
9
+ from typing import Any
12
10
 
13
11
  import yaml
12
+ from deepdiff import DeepHash
14
13
  from pydantic import BaseModel
15
14
  from sretoolbox.utils import threaded
16
15
 
@@ -27,6 +26,7 @@ from reconcile.utils import (
27
26
  gql,
28
27
  promtool,
29
28
  )
29
+ from reconcile.utils.jinja2.utils import process_extracurlyjinja2_template
30
30
  from reconcile.utils.runtime.integration import DesiredStateShardConfig
31
31
  from reconcile.utils.semver_helper import make_semver
32
32
  from reconcile.utils.structs import CommandExecutionResult
@@ -55,8 +55,8 @@ class Test(BaseModel):
55
55
  rule_path: str
56
56
  rule: dict
57
57
  rule_length: int
58
- tests: Optional[list[TestContent]]
59
- result: Optional[CommandExecutionResult] = None
58
+ tests: list[TestContent] | None
59
+ result: CommandExecutionResult | None = None
60
60
 
61
61
 
62
62
  class RuleToFetch(BaseModel):
@@ -89,7 +89,7 @@ def fetch_rule_and_tests(
89
89
  test_raw_yaml = gql.get_resource(test_path)["content"]
90
90
 
91
91
  if rule.resource["type"] == "resource-template-extracurlyjinja2":
92
- test_raw_yaml = orb.process_extracurlyjinja2_template(
92
+ test_raw_yaml = process_extracurlyjinja2_template(
93
93
  body=test_raw_yaml,
94
94
  vars=variables,
95
95
  settings=vault_settings.dict(by_alias=True),
@@ -119,18 +119,21 @@ def fetch_rule_and_tests(
119
119
  def get_rules_and_tests(
120
120
  vault_settings: AppInterfaceSettingsV1,
121
121
  thread_pool_size: int,
122
- cluster_name: Optional[str] = None,
122
+ cluster_names: Iterable[str] | None = None,
123
123
  ) -> list[Test]:
124
124
  """Iterates through all namespaces and returns a list of tests to run"""
125
125
  namespace_with_prom_rules, _ = orb.get_namespaces(
126
126
  PROVIDERS,
127
- cluster_name=cluster_name,
127
+ cluster_names=cluster_names if cluster_names else [],
128
128
  namespace_name=NAMESPACE_NAME,
129
129
  )
130
130
 
131
131
  iterable = []
132
132
  for namespace in namespace_with_prom_rules:
133
- for resource in namespace["openshiftResources"]:
133
+ prom_rules = [
134
+ r for r in namespace["openshiftResources"] if r["provider"] in PROVIDERS
135
+ ]
136
+ for resource in prom_rules:
134
137
  iterable.append(
135
138
  RuleToFetch(
136
139
  namespace=namespace,
@@ -219,14 +222,14 @@ def check_rules_and_tests(
219
222
  vault_settings: AppInterfaceSettingsV1,
220
223
  alerting_services: Iterable[str],
221
224
  thread_pool_size: int,
222
- cluster_name: Optional[str] = None,
225
+ cluster_names: Iterable[str] | None = None,
223
226
  ) -> list[Test]:
224
227
  """Fetch rules and associated tests, run checks on rules and tests if they exist
225
228
  and return a list of failed checks/tests"""
226
229
  tests = get_rules_and_tests(
227
230
  vault_settings=vault_settings,
228
231
  thread_pool_size=thread_pool_size,
229
- cluster_name=cluster_name,
232
+ cluster_names=cluster_names,
230
233
  )
231
234
  threaded.run(
232
235
  func=run_test,
@@ -241,14 +244,14 @@ def check_rules_and_tests(
241
244
 
242
245
 
243
246
  def run(
244
- dry_run: bool, thread_pool_size: int, cluster_name: Optional[str] = None
247
+ dry_run: bool, thread_pool_size: int, cluster_names: Iterable[str] | None = None
245
248
  ) -> None:
246
249
  """Check prometheus rules syntax and run the tests associated to them"""
247
250
  orb.QONTRACT_INTEGRATION = QONTRACT_INTEGRATION
248
251
  orb.QONTRACT_INTEGRATION_VERSION = QONTRACT_INTEGRATION_VERSION
249
252
 
250
253
  failed_tests = check_rules_and_tests(
251
- cluster_name=cluster_name,
254
+ cluster_names=cluster_names,
252
255
  vault_settings=get_app_interface_vault_settings(),
253
256
  alerting_services=get_alerting_services(),
254
257
  thread_pool_size=thread_pool_size,
@@ -266,14 +269,19 @@ def run(
266
269
  def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
267
270
  # early_exit doesn't support dataclasses or BaseModels yet, hence we have to store dicts
268
271
  with orb.early_exit_monkey_patch():
272
+ state_for_clusters = defaultdict(list)
273
+ tests = get_rules_and_tests(
274
+ vault_settings=get_app_interface_vault_settings(),
275
+ thread_pool_size=10,
276
+ )
277
+ for t in tests:
278
+ state_for_clusters[t.cluster_name].append(t)
279
+
269
280
  state = {
270
- "tests": [
271
- t.dict()
272
- for t in get_rules_and_tests(
273
- vault_settings=get_app_interface_vault_settings(),
274
- thread_pool_size=10,
275
- )
276
- ]
281
+ "state": {
282
+ cluster: {"shard": cluster, "hash": DeepHash(state).get(state)}
283
+ for cluster, state in state_for_clusters.items()
284
+ }
277
285
  }
278
286
 
279
287
  return state
@@ -281,7 +289,7 @@ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
281
289
 
282
290
  def desired_state_shard_config() -> DesiredStateShardConfig:
283
291
  return DesiredStateShardConfig(
284
- shard_arg_name="cluster_name",
285
- shard_path_selectors={"tests[*].cluster_name"},
292
+ shard_arg_name="cluster_names",
293
+ shard_path_selectors={"state.*.shard"},
286
294
  sharded_run_review=lambda proposal: len(proposal.proposed_shards) <= 4,
287
295
  )
reconcile/quay_base.py CHANGED
@@ -22,7 +22,10 @@ def get_quay_api_store():
22
22
  org_name = org_data["name"]
23
23
  org_key = OrgKey(instance_name, org_name)
24
24
  base_url = org_data["instance"]["url"]
25
- token = secret_reader.read(org_data["automationToken"])
25
+ automation_token = org_data["automationToken"]
26
+ if not automation_token:
27
+ continue
28
+ token = secret_reader.read(automation_token)
26
29
 
27
30
  if org_data.get("mirror"):
28
31
  mirror = OrgKey(
@@ -1,7 +1,6 @@
1
1
  import logging
2
2
  import sys
3
3
  from collections.abc import Sequence
4
- from typing import Union
5
4
 
6
5
  from reconcile.gql_definitions.quay_membership import quay_membership
7
6
  from reconcile.gql_definitions.quay_membership.quay_membership import (
@@ -81,7 +80,7 @@ def fetch_current_state(quay_api_store):
81
80
  return state
82
81
 
83
82
 
84
- def get_usernames(users: Sequence[Union[UserV1, BotV1]]) -> list[str]:
83
+ def get_usernames(users: Sequence[UserV1 | BotV1]) -> list[str]:
85
84
  return [u.quay_username for u in users if u.quay_username]
86
85
 
87
86
 
reconcile/quay_mirror.py CHANGED
@@ -1,6 +1,5 @@
1
1
  import logging
2
2
  import os
3
- import re
4
3
  import sys
5
4
  import tempfile
6
5
  import time
@@ -11,9 +10,10 @@ from collections import (
11
10
  from collections.abc import Iterable
12
11
  from typing import (
13
12
  Any,
14
- Optional,
13
+ Self,
15
14
  )
16
15
 
16
+ import requests
17
17
  from requests import Response
18
18
  from sretoolbox.container.image import (
19
19
  ImageComparisonError,
@@ -28,6 +28,7 @@ from reconcile.utils import (
28
28
  metrics,
29
29
  sharding,
30
30
  )
31
+ from reconcile.utils.helpers import match_patterns
31
32
  from reconcile.utils.instrumented_wrappers import InstrumentedImage as Image
32
33
  from reconcile.utils.instrumented_wrappers import InstrumentedSkopeo as Skopeo
33
34
  from reconcile.utils.secret_reader import SecretReader
@@ -36,12 +37,12 @@ _LOG = logging.getLogger(__name__)
36
37
 
37
38
  QONTRACT_INTEGRATION = "quay-mirror"
38
39
  CONTROL_FILE_NAME = "qontract-reconcile-quay-mirror.timestamp"
40
+ REQUEST_TIMEOUT = 60
39
41
 
40
42
  OrgKey = namedtuple("OrgKey", ["instance", "org_name"])
41
43
 
42
44
 
43
45
  class QuayMirror:
44
-
45
46
  QUAY_ORG_CATALOG_QUERY = """
46
47
  {
47
48
  quay_orgs: quay_orgs_v1 {
@@ -65,10 +66,11 @@ class QuayMirror:
65
66
  def __init__(
66
67
  self,
67
68
  dry_run: bool = False,
68
- control_file_dir: Optional[str] = None,
69
- compare_tags: Optional[bool] = None,
69
+ control_file_dir: str | None = None,
70
+ compare_tags: bool | None = None,
70
71
  compare_tags_interval: int = 86400,
71
- images: Optional[Iterable[str]] = None,
72
+ repository_urls: Iterable[str] | None = None,
73
+ exclude_repository_urls: Iterable[str] | None = None,
72
74
  ) -> None:
73
75
  self.dry_run = dry_run
74
76
  self.gqlapi = gql.get_api()
@@ -78,7 +80,8 @@ class QuayMirror:
78
80
  self.push_creds = self._get_push_creds()
79
81
  self.compare_tags = compare_tags
80
82
  self.compare_tags_interval = compare_tags_interval
81
- self.images = images
83
+ self.repository_urls = repository_urls
84
+ self.exclude_repository_urls = exclude_repository_urls
82
85
 
83
86
  self.response_cache_hits = metrics.cache_hits.labels(
84
87
  integration=QONTRACT_INTEGRATION,
@@ -109,7 +112,14 @@ class QuayMirror:
109
112
  tempfile.gettempdir(), CONTROL_FILE_NAME
110
113
  )
111
114
 
112
- self._has_enough_time_passed_since_last_compare_tags: Optional[bool] = None
115
+ self._has_enough_time_passed_since_last_compare_tags: bool | None = None
116
+ self.session = requests.Session()
117
+
118
+ def __enter__(self) -> Self:
119
+ return self
120
+
121
+ def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
122
+ self.session.close()
113
123
 
114
124
  def run(self) -> None:
115
125
  sync_tasks = self.process_sync_tasks()
@@ -130,10 +140,20 @@ class QuayMirror:
130
140
 
131
141
  @classmethod
132
142
  def process_repos_query(
133
- cls, images: Optional[Iterable[str]] = None
143
+ cls,
144
+ repository_urls: Iterable[str] | None = None,
145
+ exclude_repository_urls: Iterable[str] | None = None,
146
+ session: requests.Session | None = None,
147
+ timeout: int = REQUEST_TIMEOUT,
134
148
  ) -> defaultdict[OrgKey, list[dict[str, Any]]]:
135
149
  apps = queries.get_quay_repos()
136
150
 
151
+ if repository_urls:
152
+ repository_urls = set(repository_urls)
153
+
154
+ if exclude_repository_urls:
155
+ exclude_repository_urls = set(exclude_repository_urls)
156
+
137
157
  summary = defaultdict(list)
138
158
 
139
159
  for app in apps:
@@ -148,14 +168,25 @@ class QuayMirror:
148
168
  server_url = quay_repo["org"]["instance"]["url"]
149
169
 
150
170
  for item in quay_repo["items"]:
151
- if images and item["name"] not in images:
171
+ if item["mirror"] is None:
152
172
  continue
153
173
 
154
- if item["mirror"] is None:
174
+ mirror_url = item["mirror"]["url"]
175
+
176
+ if repository_urls and mirror_url not in repository_urls:
177
+ continue
178
+
179
+ if (
180
+ exclude_repository_urls
181
+ and mirror_url in exclude_repository_urls
182
+ ):
155
183
  continue
156
184
 
157
185
  mirror_image = Image(
158
- item["mirror"]["url"], response_cache=cls.response_cache
186
+ mirror_url,
187
+ response_cache=cls.response_cache,
188
+ session=session,
189
+ timeout=timeout,
159
190
  )
160
191
  if mirror_image.registry == "docker.io" and item["public"]:
161
192
  _LOG.error(
@@ -166,39 +197,53 @@ class QuayMirror:
166
197
  sys.exit(ExitCodes.ERROR)
167
198
 
168
199
  org_key = OrgKey(instance, org)
169
- summary[org_key].append(
170
- {
171
- "name": item["name"],
172
- "mirror": item["mirror"],
173
- "server_url": server_url,
174
- }
175
- )
200
+ summary[org_key].append({
201
+ "name": item["name"],
202
+ "mirror": item["mirror"],
203
+ "server_url": server_url,
204
+ })
176
205
  return summary
177
206
 
178
207
  @staticmethod
179
- def sync_tag(tags, tags_exclude, candidate):
180
- if tags is not None:
181
- for tag in tags:
182
- if re.match(tag, candidate):
183
- return True
184
- # When tags is defined, we don't look at
185
- # tags_exclude
186
- return False
187
-
188
- if tags_exclude is not None:
189
- for tag_exclude in tags_exclude:
190
- if re.match(tag_exclude, candidate):
191
- return False
208
+ def sync_tag(
209
+ tags: Iterable[str] | None,
210
+ tags_exclude: Iterable[str] | None,
211
+ candidate: str,
212
+ ) -> bool:
213
+ """
214
+ Determine if the candidate tag should sync, tags_exclude check take precedence.
215
+ :param tags: regex patterns to filter, match means to sync, None means no filter
216
+ :param tags_exclude: regex patterns to filter, match means not to sync, None means no filter
217
+ :param candidate: tag to check
218
+ :return: bool, True means to sync, False means not to sync
219
+ """
220
+ if not tags and not tags_exclude:
192
221
  return True
193
222
 
194
- # Both tags and tags_exclude are None, so
195
- # tag must be synced
196
- return True
223
+ if not tags:
224
+ # only tags_exclude provided
225
+ assert tags_exclude # mypy can't infer not None
226
+ return not match_patterns(tags_exclude, candidate)
227
+
228
+ if not tags_exclude:
229
+ # only tags provided
230
+ return match_patterns(tags, candidate)
231
+
232
+ # both tags and tags_exclude provided
233
+ return not match_patterns(
234
+ tags_exclude,
235
+ candidate,
236
+ ) and match_patterns(
237
+ tags,
238
+ candidate,
239
+ )
197
240
 
198
241
  def process_sync_tasks(self):
199
242
  if self.is_compare_tags:
200
243
  _LOG.warning("Making a compare-tags run. This is a slow operation.")
201
- summary = self.process_repos_query(self.images)
244
+ summary = self.process_repos_query(
245
+ self.repository_urls, self.exclude_repository_urls
246
+ )
202
247
  sync_tasks = defaultdict(list)
203
248
  for org_key, data in summary.items():
204
249
  org = org_key.org_name
@@ -209,6 +254,8 @@ class QuayMirror:
209
254
  username=push_creds[0],
210
255
  password=push_creds[1],
211
256
  response_cache=self.response_cache,
257
+ session=self.session,
258
+ timeout=REQUEST_TIMEOUT,
212
259
  )
213
260
 
214
261
  mirror_url = item["mirror"]["url"]
@@ -228,6 +275,8 @@ class QuayMirror:
228
275
  username=username,
229
276
  password=password,
230
277
  response_cache=self.response_cache,
278
+ session=self.session,
279
+ timeout=REQUEST_TIMEOUT,
231
280
  )
232
281
 
233
282
  tags = item["mirror"].get("tags")
@@ -305,13 +354,11 @@ class QuayMirror:
305
354
  _LOG.debug(
306
355
  "Image %s and mirror %s are out of sync", downstream, upstream
307
356
  )
308
- sync_tasks[org_key].append(
309
- {
310
- "mirror_url": str(upstream),
311
- "mirror_creds": mirror_creds,
312
- "image_url": str(downstream),
313
- }
314
- )
357
+ sync_tasks[org_key].append({
358
+ "mirror_url": str(upstream),
359
+ "mirror_creds": mirror_creds,
360
+ "image_url": str(downstream),
361
+ })
315
362
 
316
363
  return sync_tasks
317
364
 
@@ -336,20 +383,17 @@ class QuayMirror:
336
383
  @staticmethod
337
384
  def check_compare_tags_elapsed_time(path, interval) -> bool:
338
385
  try:
339
- with open(path, "r") as file_obj:
386
+ with open(path, encoding="locale") as file_obj:
340
387
  last_compare_tags = float(file_obj.read())
341
388
  except FileNotFoundError:
342
389
  return True
343
390
 
344
391
  next_compare_tags = last_compare_tags + interval
345
- if time.time() >= next_compare_tags:
346
- return True
347
-
348
- return False
392
+ return time.time() >= next_compare_tags
349
393
 
350
394
  @staticmethod
351
395
  def record_timestamp(path) -> None:
352
- with open(path, "w") as file_object:
396
+ with open(path, "w", encoding="locale") as file_object:
353
397
  file_object.write(str(time.time()))
354
398
 
355
399
  def _get_push_creds(self):
@@ -372,20 +416,26 @@ class QuayMirror:
372
416
 
373
417
  def run(
374
418
  dry_run,
375
- control_file_dir: Optional[str],
376
- compare_tags: Optional[bool],
419
+ control_file_dir: str | None,
420
+ compare_tags: bool | None,
377
421
  compare_tags_interval: int,
378
- images: Optional[Iterable[str]],
422
+ repository_urls: Iterable[str] | None,
423
+ exclude_repository_urls: Iterable[str] | None,
379
424
  ):
380
- quay_mirror = QuayMirror(
381
- dry_run, control_file_dir, compare_tags, compare_tags_interval, images
382
- )
383
- quay_mirror.run()
425
+ with QuayMirror(
426
+ dry_run,
427
+ control_file_dir,
428
+ compare_tags,
429
+ compare_tags_interval,
430
+ repository_urls,
431
+ exclude_repository_urls,
432
+ ) as quay_mirror:
433
+ quay_mirror.run()
384
434
 
385
435
 
386
436
  def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
387
- quay_mirror = QuayMirror(dry_run=True)
388
- return {
389
- "repos": quay_mirror.process_repos_query(),
390
- "orgs": quay_mirror.push_creds,
391
- }
437
+ with QuayMirror(dry_run=True) as quay_mirror:
438
+ return {
439
+ "repos": quay_mirror.process_repos_query(session=quay_mirror.session),
440
+ "orgs": quay_mirror.push_creds,
441
+ }